This Rmarkdown file assesses the output of CheckV, DeepVirFinder, Kaiju, VIBRANT, VirSorter, and VirSorter2 on multiple training sets of microbial DNA, primarily from NCBI. Created from fungal, viral, bacterial, archeael, protist, and plasmid DNA sequences

Please reach out to James Riddell () or Bridget Hegarty () regarding any issues, or open an issue on github.

library(ggplot2)
library(plyr)
library(reshape2)
library(viridis)
library(tidyr)
library(dplyr)
library(readr)
library(data.table)
library(pROC)
Type 'citation("pROC")' for a citation.

Attaching package: ‘pROC’

The following objects are masked from ‘package:stats’:

    cov, smooth, var
library(here)

Inputs

  1. For this script’s inputs, the user must merge each viral identification tool output file into one tab-separated file. Replace the filenames with their paths if needed into the variables in the ‘inputs’ chunk.

    General filenames for each tool: Checkv: quality_summary.tsv VIBRANT: VIBRANT_genome_quality_${assembly}.tsv Virsorter: VIRSorter_global-phage-signal.csv Virsorter2: final-viral-score.tsv DeepVirFinder: ${assembly}.fasta_gt2500bp_dvfpred.txt Kaiju: ${assembly}.kaiju.names.out

  2. Make sure all fasta headers (assembly, contig) are consistent within and across tools. Chunks for each tool do contain some lines for cleaning up these features, but due to their variability it will be the user’s responsibility to make sure they match across tools.

  3. Check each chunk and ensure all columns are accounted for.

  4. This script is designed for contigs > 3000 basepairs. It can be modified to be higher or lower, but going lower will greatly increase the size of the dataframe and memory usage.

# dataset name for file organization and outputs for metrics file
dataset_name <- "testing_set"
# checkV
checkV_path <- "../ToolOutput/testing_sets_checkv_output.tsv"
# VIBRANT
vibrant_path <- "../ToolOutput/testing_sets_vibrant_output.tsv"
# DeepVirFinder
dvf_path <- "../ToolOutput/testing_sets_deepvirfinder_output.tsv"
# Virsorter
vs_path <- "../ToolOutput/testing_sets_virsorter_output.tsv"
# Virsorter2
vs2_path <- "../ToolOutput/testing_sets_virsorter2_output.tsv"
# Kaiju
kj_path <- "../ToolOutput/merged.nreuk.kaiju.names.out"
# KB cutoff
KB_CUTOFF <- 3000

All Viral Contigs

checkV

checkV <- fread(checkV_path, 
                sep="\t",
                header = T, 
                select = c(
                    'Index',
                    'contig_id',
                    'provirus',
                    'completeness',
                    'contamination',
                    'viral_genes',
                    'host_genes',
                    'gene_count',
                    'contig_length',
                    'checkv_quality'
                    )
                ) %>% 
    rename(
        contig = contig_id,
        checkv_provirus = provirus,
        checkv_completeness = completeness,
        checkv_contamination = contamination,
        checkv_viral_genes = viral_genes,
        checkv_host_genes = host_genes,
        checkv_total_genes = gene_count,
        checkv_length = contig_length
        )
checkV$method = 'checkv'
checkV <- separate(checkV, col = contig, into = c("seqtype", "contig"), sep="--")
checkV$contig <- sub("\\.", "_", checkV$contig)
checkV$contig <- sub("\\|", "_", checkV$contig)
checkV <- checkV[!duplicated(paste(checkV$contig, checkV$Index)),]

VIBRANT

vb_c <- fread(vibrant_path,
              header = T,
              sep = "\t",
              select = c(
                  'Index',
                  'scaffold',
                  'type',
                  'Quality'
                  )
              ) %>%
    rename(
        contig = scaffold,
        vibrant_quality = Quality
        )
vb_c$method <- "vibrant"
vb_c$vibrant_prophage <- "No"
vb_c$vibrant_prophage[grep("_fragment_", vb_c$contig)] <- "Yes"
vb_c <- separate(vb_c, col = contig, into = c("seqtype", "contig"), sep="--")
vb_c$contig <- gsub("_fragment_.*", "", vb_c$contig)
vb_c$contig <- sub("\\.", "_", vb_c$contig)
vb_c <- separate(vb_c, col=contig, into="contig", remove=T, sep = " ")
vb_c <- vb_c[!duplicated(paste(vb_c$contig, vb_c$Index)),]

DeepVirFinder

dvf_c <- fread(dvf_path,
               header = T,
               sep = "\t",
               select = c(
                   'Index',
                   'name',
                   'score',
                   'pvalue'
                   )
               ) %>% 
    rename(
        contig = name
        )
dvf_c$contig <- sub("\\.", "_", dvf_c$contig)
dvf_c <- separate(dvf_c, col = contig, into = c("seqtype", "contig"), sep="--")
dvf_c$bh_pvalue <- p.adjust(dvf_c$pvalue, method="BH")
dvf_c <- dvf_c[!duplicated(paste(dvf_c$contig, dvf_c$Index)),]

VirSorter

vs_c <- fread(vs_path,
              select = c(
                  'index',
                  'contig',
                  'category'
                  )
              ) %>% 
    rename(
        Index = index
        )
vs_c$contig <- sub("VIRSorter_", "", vs_c$contig)
vs_c$contig <- sub("-circular", "", vs_c$contig)
vs_c <- separate(vs_c, col = `contig`, into = c("seqtype", "contig"), sep="--")
vs_c$contig <- sub("\\.", "_", vs_c$contig)
vs_c <- vs_c %>% drop_na(contig)
vs_c <- vs_c[!duplicated(paste(vs_c$contig, vs_c$Index)),]

VirSorter2

vs2_c <- fread(vs2_path,
                    header = T,
                    sep = '\t',
                    select = c(
                        'Index',
                        'seqname',
                        'dsDNAphage',
                        'ssDNA',
                        'max_score',
                        'max_score_group',
                        'hallmark',
                        'viral',
                        'cellular'
                    )
               ) %>% 
              separate(
                  col = seqname,
                  into = c("contig", "vs2type"), 
                  sep = "\\|\\|",
                  remove = T
                  )
vs2_c$contig <- sub("\\.", "_", vs2_c$contig)
vs2_c <- separate(vs2_c, col = contig, into = c("seqtype", "contig"), sep="--")
vs2_c <- vs2_c[!duplicated(paste(vs2_c$contig, vs2_c$Index)),]

Kaiju

kj_c <- read_tsv(kj_path, col_names = T)
Warning: One or more parsing issues, see `problems()` for details
Rows: 96361 Columns: 9
── Column specification ───────────────────────────────────────────────────────────────────────────────────────────
Delimiter: "\t"
chr (5): Classified, Contig, IDs_all, Seq, Name
dbl (3): Index, NCBI_taxon, len

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
kj_c$Contig <- sub("\\.", "_", kj_c$Contig)
kj_c <- separate(kj_c, col = Contig, into = c("seqtype", "contig"), sep="--")
kj_c <- separate(kj_c, col = Name, into = c("Kaiju_Viral","Kingdom"), sep=";")
Warning: Expected 2 pieces. Additional pieces discarded in 84573 rows [2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, ...].
kj_c$contig <- sub("\\.", "_", kj_c$contig)
kj_c <- kj_c[!duplicated(paste(kj_c$contig, kj_c$Index)),]

Quick glimpse of cellular vs viral sequence classification by Kaiju by assembly

table(kj_c$seqtype, kj_c$Kaiju_Viral)
          
           cellular organisms Viruses
  archaea                9705      41
  bacteria              59945     164
  fungi                   861     104
  plasmid                4972       3
  protist                 557       2
  virus                  4116    4099

Merging

viruses <- full_join(x=checkV, y=kj_c, by = c("Index", "contig", "seqtype"))
viruses <- full_join(x=viruses, y=dvf_c, by = c("Index", "contig", "seqtype"))
viruses <- full_join(x=viruses, y=vb_c, by = c("Index", "contig", "seqtype"))
viruses <- full_join(x=viruses, y=vs_c, by = c("Index", "contig", "seqtype"))
viruses <- full_join(x=viruses, y=vs2_c, by = c("Index", "contig", "seqtype"))

Remove contigs not greater than the basepair length cutoff (3000)

viruses <- viruses %>% filter(checkv_length > KB_CUTOFF)

Use the next code chunk to check if any contigs are missing from checkv. If yes, then there is a mix up in contig names since checkv should contain all contig names even if they are identified as non-viral.

v_missing <- viruses[is.na(viruses$checkv_uniq_contig),]

calculate percent viral/host/unknown

viruses$percent_host <- viruses$checkv_host_genes/viruses$checkv_total_genes*100
viruses$percent_viral <- viruses$checkv_viral_genes/viruses$checkv_total_genes*100
viruses$percent_unknown <- 100-(viruses$checkv_host_genes+viruses$checkv_viral_genes)/viruses$checkv_total_genes*100

get rid of NAs for downstream processing

# checkV
viruses$percent_viral[is.na(viruses$percent_viral)] <- 0
viruses$percent_unknown[is.na(viruses$percent_unknown)] <- 0
# VIBRANT
viruses$vibrant_quality[is.na(viruses$vibrant_quality)] <- 0
# DeepVirFinder
viruses$score[is.na(viruses$score)] <- 0
viruses$bh_pvalue[is.na(viruses$bh_pvalue)] <- 0
# VirSorter2
viruses$viral[is.na(viruses$viral)] <- 0
viruses$hallmark[is.na(viruses$hallmark)] <- 0
#Virsorter
viruses$category[is.na(viruses$category)] <- 0
# Kaiju
viruses$Kaiju_Viral[is.na(viruses$Kaiju_Viral)] <- "unknown"
viruses$Kingdom[is.na(viruses$Kingdom)] <- "unknown"

This section defines a viralness score “keep_score” based on the tool classifications. A final keep_score above 1 indicates we will keep that sequence and call it viral.

VIBRANT Quality == “High Quality Draft”: +1 Quality == “Medium Quality Draft”: +1 Quality == “Low Quality Draft” & provirus == TRUE: +0.5

Virsorter2 Viral >= 50: +0.5 Viral >= 0.95: +0.5

Virsorter category == 1,2,4,5: +1 category == 3,6: +0.5

DeepVirFinder: Score >= 0.7: +0.5 Score >= 0.9: +0.5

Kaiju: Kaiju_viral = “cellular organisms”: -1 Kaiju_viral = “Viruses”: +1

CheckV If %unknown >= 75: +0.5 Hallmark > 2: +1 viral_genes == 0 and host_genes >= 1: keep_score = 0 If 3*viral_genes <= host_genes: keep_score = 0 If length > 50,000 and hallmark == 0: keep_score = 0

This script produces visualizations of these combined viral scorings and includes ecological metrics like alpha diversity.

You can decide which combination is appropriate for them and only need use the tools appropriate for your data.

getting_viral_set_1 <- function(input_seqs,
                                include_vibrant=FALSE, 
                                include_virsorter2=FALSE,
                                include_deepvirfinder=FALSE,
                                include_tuning=FALSE,
                                include_kaiju=FALSE,
                                include_virsorter=FALSE) {
  
  keep_score <- rep(0, nrow(input_seqs))
  
  if (include_vibrant) {
    keep_score[input_seqs$vibrant_quality=="high quality draft"] <- keep_score[input_seqs$vibrant_quality=="high quality draft"] + 1
    keep_score[input_seqs$vibrant_quality=="medium quality draft"] <- keep_score[input_seqs$vibrant_quality=="medium quality draft"] + 1
    keep_score[input_seqs$vibrant_quality=="low quality draft" & input_seqs$provirus=="Yes"] <- keep_score[input_seqs$vibrant_quality=="low quality draft" & input_seqs$provirus=="Yes"] + 0.5
#    keep_score[input_seqs$vibrant_quality=="low quality draft"] <- keep_score[input_seqs$vibrant_quality=="low quality draft"] + 0.5
  }
  
  if (include_virsorter2) {
    keep_score[input_seqs$viral>=50] <- keep_score[input_seqs$viral>=50] + 0.5
    keep_score[input_seqs$viral>=95] <- keep_score[input_seqs$viral>=95] + 0.5
  }
  
  if (include_virsorter) {
    keep_score[input_seqs$category==1] <- keep_score[input_seqs$category==1] + 1
    keep_score[input_seqs$category==2] <- keep_score[input_seqs$category==2] + 1
    keep_score[input_seqs$category==3] <- keep_score[input_seqs$category==3] + 0.5
    keep_score[input_seqs$category==4] <- keep_score[input_seqs$category==4] + 1
    keep_score[input_seqs$category==5] <- keep_score[input_seqs$category==5] + 1
    keep_score[input_seqs$category==6] <- keep_score[input_seqs$category==6] + 0.5
  }
  
  if (include_deepvirfinder) {
    keep_score[input_seqs$score>=0.7 & input_seqs$contig_length<20000] <- keep_score[input_seqs$score>=0.7 & input_seqs$contig_length<20000] + 0.5
   keep_score[input_seqs$score>=0.9 & input_seqs$contig_length<20000] <- keep_score[input_seqs$score>=0.9 & input_seqs$contig_length<20000] + 0.5
  }
  
  if (include_kaiju) {
    keep_score[input_seqs$Kaiju_Viral=="cellular organisms"] <- keep_score[input_seqs$Kaiju_Viral=="cellular organisms"] - 1
    keep_score[input_seqs$Kaiju_Viral=="Viruses"] <- keep_score[input_seqs$Kaiju_Viral=="Viruses"] + 1
  }
  
  if (include_tuning) {
    keep_score[input_seqs$hallmark>2] <- keep_score[input_seqs$hallmark>2] + 1
    keep_score[input_seqs$percent_unknown>=75] <- keep_score[input_seqs$percent_unknown>=75] + 0.5
    keep_score[input_seqs$percent_viral>=50] <- keep_score[input_seqs$percent_viral>=50] + 0.5
    #keep_score[input_seqs$hallmark>=(input_seqs$checkv_viral_genes/5)] <- keep_score[input_seqs$hallmark>=(input_seqs$checkv_viral_genes/5)] + 1 #add some ratio
    keep_score[input_seqs$viral_genes==0 & input_seqs$host_genes>=1] <- 0
    keep_score[((input_seqs$viral_genes*3) <= input_seqs$host_genes) & input_seqs$checkv_provirus=="No"] <- 0 # consider accounting for provirus designation
#    keep_score[(input_seqs$viral_genes*3) <= input_seqs$host_genes] <- 0 # consider accounting for provirus designation
    keep_score[input_seqs$contig_length>50000 & input_seqs$hallmark==0] <- 0
  }
  
  return(keep_score)
  
}

Assessing performance against the “truth”

note that this is only as accurate as the annotations of the input sequences

this function calculates the precision, recall, and F1 score for each pipeline

assess_performance <- function(seqtype, keep_score) {
  
  truepositive <- rep("not viral", length(seqtype))
  truepositive[seqtype=="virus"] <- "viral"
  
  #make confusion matrix
  confusion_matrix <- rep("true negative", length(keep_score))
  confusion_matrix[truepositive=="viral" & keep_score<=1] <- "false negative"
  confusion_matrix[truepositive=="viral" & keep_score>=1] <- "true positive"
  confusion_matrix[truepositive=="not viral" & keep_score>=1] <- "false positive"
  
  TP <- table(confusion_matrix)[4]
  FP <- table(confusion_matrix)[2]
  TN <- table(confusion_matrix)[3]
  FN <- table(confusion_matrix)[1]
  
  precision <- TP/(TP+FP)
  recall <- TP/(TP+FN)
  F1 <- 2*precision*recall/(precision+recall)
  
  MCC <- (TP*TN-FP*FN)/sqrt(as.numeric(TP+FP)*as.numeric(TP+FN)*as.numeric(TN+FP)*as.numeric(TN+FN))
  
  AUC <- round(auc(truepositive, keep_score),4)
  
  #by type metrics
  fungal_FP <- table(confusion_matrix[seqtype=="fungi"])[2]
  bacterial_FP <- table(confusion_matrix[seqtype=="bacteria"])[2]
  viral_FN <- table(confusion_matrix[seqtype=="virus"])[1]
  
  performance <- c(precision, recall, F1, MCC, AUC, fungal_FP, bacterial_FP, viral_FN)
  names(performance) <- c("precision", "recall", "F1", "MCC", "AUC", "fungal_FP",
                          "bacterial_FP", "viral_FN")
  
  return(performance)
}

combination of tools list

combos_list <- read_csv("combinations_list.csv", col_names = T)
Rows: 63 Columns: 6
── Column specification ───────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
dbl (6): CheckV, DVF, Kaiju, VIBRANT, VS, VS2

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

this function builds a list of all of the combinations that the user wants to test. In this case, we’re comparing the performance of all unique combinations of the six tools.

build_score_list <- function(input_seqs, combos) {
  output <- data.frame(precision=rep(0, nrow(combos)),
                       recall=rep(0, nrow(combos)),
                       F1=rep(0, nrow(combos)),
                       MCC=rep(0, nrow(combos)),
                       AUC=rep(0, nrow(combos)),
                       fungal_FP=rep(0, nrow(combos)),
                       bacterial_FP=rep(0, nrow(combos)),
                       viral_FN=rep(0, nrow(combos)))
  for (i in 1:nrow(combos)) {
    keep_score <- getting_viral_set_1(input_seqs, include_vibrant = combos$VIBRANT[i],
                                            include_virsorter = combos$VS[i],
                                            include_virsorter2 = combos$VS2[i],
                                            include_tuning = combos$CheckV[i],
                                            include_kaiju = combos$Kaiju[i],
                                            include_deepvirfinder = combos$DVF[i])
  
    output[i,1:8] <- assess_performance(input_seqs$seqtype, keep_score)
    
    output$toolcombo[i] <- paste(combos$CheckV[i],combos$DVF[i],
                                 combos$Kaiju[i], combos$VIBRANT[i],
                                 combos$VS[i], combos$VS2[i])
  }
  
  output[is.na(output)] <- 0
  
  #return(keep_score)
  return (output)
}

Calculate the performance of each pipeline

accuracy_scores <- build_score_list(viruses[viruses$Index==1], combos_list)
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
accuracy_scores <- data.frame(testing_set_index=rep(0, nrow(combos_list)*10),
                      precision=rep(0, nrow(combos_list)*10),
                       recall=rep(0, nrow(combos_list)*10),
                       F1=rep(0, nrow(combos_list)*10),
                       MCC=rep(0, nrow(combos_list)*10), 
                      AUC=rep(0, nrow(combos_list)*10),
                      fungal_FP=rep(0, nrow(combos_list)*10),
                      bacterial_FP=rep(0, nrow(combos_list)*10),
                      viral_FN=rep(0, nrow(combos_list)*10))
accuracy_scores <- cbind(testing_set_index=rep(1, nrow(combos_list)),
                              build_score_list(viruses[viruses$Index==1], combos_list))
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
for (i in 2:10) {
  accuracy_scores <- rbind(accuracy_scores,
                           cbind(testing_set_index=rep(i, nrow(combos_list)),
                              build_score_list(viruses[viruses$Index==i], combos_list)))
}
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
Setting levels: control = not viral, case = viral
Setting direction: controls < cases
library("stringr")
accuracy_scores$numtools <- str_count(accuracy_scores$toolcombo, "1")
#accuracy_scores <- accuracy_scores[order(accuracy_scores$numtools, decreasing=F),]
accuracy_scores <- accuracy_scores[order(accuracy_scores$MCC, decreasing=F),]
accuracy_scores$toolcombo <- factor(accuracy_scores$toolcombo, levels = unique(accuracy_scores$toolcombo))
accuracy_scores$numtools <- as.factor(accuracy_scores$numtools)

Visualize how the precision, recall, and F1 scores change across pipelines.

pal <- ggthemes::tableau_color_pal(palette="Tableau 10", type="regular")
p2 <- ggplot(accuracy_scores, aes(x=toolcombo, y=F1, 
                                  color=numtools, fill=numtools)) +
  geom_point(alpha=0.5) +
  theme_light() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank(),
    legend.position = "bottom",
    axis.text.y=element_text(size=14),
    axis.text.x=element_text(size=14, angle = 90),
    legend.text=element_text(size=12),
    axis.title=element_text(size=16),
  ) +
  xlab("Tool Combination (CV, DVF, KJ, VB, VS, VS2)") +
  ylab("F1 Score")
p2

ggplot(accuracy_scores, aes(x=toolcombo, y=precision, 
                                  color=numtools, fill=numtools)) +
  geom_point(alpha=0.5) +
  theme_light() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank(),
    legend.position = "bottom",
    axis.text.y=element_text(size=14),
    axis.text.x=element_text(size=14, angle = 90),
    legend.text=element_text(size=12),
    axis.title=element_text(size=16),
  ) +
  xlab("Tool Combination (CV, DVF, KJ, VB, VS, VS2)") +
  ylab("Precision")

ggplot(accuracy_scores, aes(x=toolcombo, y=recall, 
                                  color=numtools, fill=numtools)) +
  geom_point(alpha=0.5) +
  theme_light() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank(),
    legend.position = "bottom",
    axis.text.y=element_text(size=14),
    axis.text.x=element_text(size=14, angle = 90),
    legend.text=element_text(size=12),
    axis.title=element_text(size=16),
  ) +
  xlab("Tool Combination (CV, DVF, KJ, VB, VS, VS2)") +
  ylab("Recall")

ggplot(accuracy_scores, aes(x=precision, y=recall, 
                                  color=numtools, fill=numtools)) +
  geom_point(alpha=0.5) +
  theme_light() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank(),
    legend.position = "bottom",
    axis.text.y=element_text(size=14),
    axis.text.x=element_text(size=14, angle = 90),
    legend.text=element_text(size=12),
    axis.title=element_text(size=16),
  ) +
  xlab("Precision") +
  ylab("Recall")

ggplot(accuracy_scores, aes(x=toolcombo, y=abs(precision-recall), 
                                  color=numtools, fill=numtools)) +
  geom_point(alpha=0.5) +
  theme_light() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank(),
    legend.position = "bottom",
    axis.text.y=element_text(size=14),
    axis.text.x=element_text(size=14, angle = 90),
    legend.text=element_text(size=12),
    axis.title=element_text(size=16),
  ) +
  xlab("Tool Combination (CV, DVF, KJ, VB, VS, VS2)") +
  ylab("Precision-Recall")

ggplot(accuracy_scores, aes(x=toolcombo, y=MCC, 
                                  color=numtools, fill=numtools)) +
  geom_point(alpha=0.5) +
  theme_light() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank(),
    legend.position = "bottom",
    axis.text.y=element_text(size=14),
    axis.text.x=element_text(size=14, angle = 90),
    legend.text=element_text(size=12),
    axis.title=element_text(size=16),
  ) +
  xlab("Tool Combination (CV, DVF, KJ, VB, VS, VS2)") +
  ylab("MCC")

ggplot(accuracy_scores, aes(x=toolcombo, y=AUC, 
                                  color=numtools, fill=numtools)) +
  geom_point(alpha=0.5) +
  theme_light() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank(),
    legend.position = "bottom",
    axis.text.y=element_text(size=14),
    axis.text.x=element_text(size=14, angle = 90),
    legend.text=element_text(size=12),
    axis.title=element_text(size=16),
  ) +
  xlab("Tool Combination (CV, DVF, KJ, VB, VS, VS2)") +
  ylab("AUC")

ggplot(accuracy_scores, aes(x=toolcombo, y=fungal_FP, 
                                  color=numtools, fill=numtools)) +
  geom_point(alpha=0.5) +
  theme_light() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank(),
    legend.position = "bottom",
    axis.text.y=element_text(size=14),
    axis.text.x=element_text(size=14, angle = 90),
    legend.text=element_text(size=12),
    axis.title=element_text(size=16),
  ) +
  xlab("Tool Combination (CV, DVF, KJ, VB, VS, VS2)") +
  ylab("Fungal False Positives")

ggplot(accuracy_scores, aes(x=toolcombo, y=bacterial_FP, 
                                  color=numtools, fill=numtools)) +
  geom_point(alpha=0.5) +
  theme_light() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank(),
    legend.position = "bottom",
    axis.text.y=element_text(size=14),
    axis.text.x=element_text(size=14, angle = 90),
    legend.text=element_text(size=12),
    axis.title=element_text(size=16),
  ) +
  xlab("Tool Combination (CV, DVF, KJ, VB, VS, VS2)") +
  ylab("Bacterial False Positives")

ggplot(accuracy_scores, aes(x=toolcombo, y=viral_FN, 
                                  color=numtools, fill=numtools)) +
  geom_point(alpha=0.5) +
  theme_light() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank(),
    legend.position = "bottom",
    axis.text.y=element_text(size=14),
    axis.text.x=element_text(size=14, angle = 90),
    legend.text=element_text(size=12),
    axis.title=element_text(size=16),
  ) +
  xlab("Tool Combination (CV, DVF, KJ, VB, VS, VS2)") +
  ylab("Viral False Negatives")

Experimenting

high precision example

viruses$keep_score_high_precision <- getting_viral_set_1(viruses, include_deepvirfinder = F,
                                              include_vibrant = T,
                                              include_virsorter2 = F,
                                              include_kaiju = T,
                                              include_tuning = T,
                                              include_virsorter = F)
viruses$confusion_matrix_high_precision <- "true negative"
viruses$confusion_matrix_high_precision[viruses$seqtype=="virus" & viruses$keep_score_high_precision<=1] <- "false negative"
viruses$confusion_matrix_high_precision[viruses$seqtype=="virus" & viruses$keep_score_high_precision>=1] <- "true positive"
viruses$confusion_matrix_high_precision[viruses$seqtype!="virus" & viruses$keep_score_high_precision>=1] <- "false positive"

visualizing confusion matrix by taxa

confusion_by_taxa <- melt(table(viruses$confusion_matrix_high_precision, viruses$seqtype, viruses$Index))
Warning in melt(table(viruses$confusion_matrix_high_precision, viruses$seqtype,  :
  The melt generic in data.table has been passed a table and will attempt to redirect to the relevant reshape2 method; please note that reshape2 is deprecated, and this redirection is now deprecated as well. To continue using melt methods from reshape2 while both libraries are attached, e.g. melt.list, you can prepend the namespace like reshape2::melt(table(viruses$confusion_matrix_high_precision, viruses$seqtype,     viruses$Index)). In the next version, this warning will become an error.
colnames(confusion_by_taxa) <- c("confusion_matrix", "seqtype","Index", "count")
pal <- ggthemes::tableau_color_pal(palette="Tableau 10", type="regular")
ggplot(confusion_by_taxa, aes(x=count, y=as.factor(Index),
                   fill=confusion_matrix,
                   color=confusion_matrix)) +
  geom_bar(stat="identity") +
  theme_light() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank(),
    legend.position = "bottom",
    axis.text.y=element_text(size=14),
    axis.text.x=element_text(size=14),
    legend.text=element_text(size=12),
    axis.title=element_text(size=16),
  ) +
  scale_fill_manual(name="",
                     values = alpha(rev(pal(4)), 0.5),
                    labels=c("false negative", "false positive", 
                             "true negative", "true positive")) +
  scale_color_manual(name="",
                     values = alpha(rev(pal(4)), 1),
                    labels=c("false negative", "false positive", 
                             "true negative", "true positive")) +
  xlab("Number of Sequences") +
  ylab("") + 
  facet_wrap(~seqtype, scales = "free") +
  coord_flip()

 ggplot(viruses, aes(x=checkv_viral_genes, y=confusion_matrix_high_precision,
                   fill=confusion_matrix_high_precision,
                   color=confusion_matrix_high_precision)) +
  geom_boxplot(alpha=0.3) +
  theme_light() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank(),
    legend.position = "bottom",
    axis.text.y=element_text(size=14),
    axis.text.x=element_text(size=14),
    legend.text=element_text(size=12),
    axis.title=element_text(size=16),
  ) +
  scale_fill_manual(name="",
                     values = alpha(rev(pal(4)), 0.5),
                    labels=c("false negative", "false positive", 
                             "true negative", "true positive")) +
  scale_color_manual(name="",
                     values = alpha(rev(pal(4)), 1),
                    labels=c("false negative", "false positive", 
                             "true negative", "true positive")) +
  xlab("Number of Viral Sequences") +
  ylab("") + 
  facet_wrap(~seqtype, scales = "free") +
  coord_flip()


 ggplot(viruses, aes(x=percent_viral, y=confusion_matrix_high_precision,
                   fill=confusion_matrix_high_precision,
                   color=confusion_matrix_high_precision)) +
  geom_boxplot(alpha=0.3) +
  theme_light() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank(),
    legend.position = "bottom",
    axis.text.y=element_text(size=14),
    axis.text.x=element_text(size=14),
    legend.text=element_text(size=12),
    axis.title=element_text(size=16),
  ) +
  scale_fill_manual(name="",
                     values = alpha(rev(pal(4)), 0.5),
                    labels=c("false negative", "false positive", 
                             "true negative", "true positive")) +
  scale_color_manual(name="",
                     values = alpha(rev(pal(4)), 1),
                    labels=c("false negative", "false positive", 
                             "true negative", "true positive")) +
  xlab("Percent Genes Viral") +
  ylab("") + 
  facet_wrap(~seqtype, scales = "free") +
  coord_flip()


 ggplot(viruses, aes(x=hallmark, y=confusion_matrix_high_precision,
                   fill=confusion_matrix_high_precision,
                   color=confusion_matrix_high_precision)) +
  geom_boxplot(alpha=0.3) +
  theme_light() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank(),
    legend.position = "bottom",
    axis.text.y=element_text(size=14),
    axis.text.x=element_text(size=14),
    legend.text=element_text(size=12),
    axis.title=element_text(size=16),
  ) +
  scale_fill_manual(name="",
                     values = alpha(rev(pal(4)), 0.5),
                    labels=c("false negative", "false positive", 
                             "true negative", "true positive")) +
  scale_color_manual(name="",
                     values = alpha(rev(pal(4)), 1),
                    labels=c("false negative", "false positive", 
                             "true negative", "true positive")) +
  xlab("Number of Hallmark Genes") +
  ylab("") + 
  facet_wrap(~seqtype, scales = "free") +
  coord_flip()

 
ggplot(viruses, aes(x=hallmark, y=checkv_viral_genes,
                   fill=confusion_matrix_high_precision,
                   color=confusion_matrix_high_precision)) +
  geom_point(alpha=0.3) +
  theme_light() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank(),
    legend.position = "bottom",
    axis.text.y=element_text(size=14),
    axis.text.x=element_text(size=14),
    legend.text=element_text(size=12),
    axis.title=element_text(size=16),
  ) +
  scale_fill_manual(name="",
                     values = alpha(rev(pal(4)), 0.5),
                    labels=c("false negative", "false positive", 
                             "true negative", "true positive")) +
  scale_color_manual(name="",
                     values = alpha(rev(pal(4)), 1),
                    labels=c("false negative", "false positive", 
                             "true negative", "true positive")) +
  xlab("Number of Hallmark Genes") +
  ylab("Number of Viral Genes") + 
  facet_wrap(~seqtype, scales = "free") +
  coord_flip()

viruses_false_positive <- viruses[viruses$confusion_matrix_high_precision=="false positive",]
viruses_false_negative <- viruses[viruses$confusion_matrix_high_precision=="false negative",]
ggplot(viruses, aes(x=hallmark, y=checkv_viral_genes,
                   fill=checkv_length,
                   color=checkv_length,
                   shape=checkv_provirus)) +
  geom_point(alpha=0.3) +
  theme_light() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank(),
    legend.position = "bottom",
    axis.text.y=element_text(size=14),
    axis.text.x=element_text(size=14),
    legend.text=element_text(size=12),
    axis.title=element_text(size=16),
  ) +
  xlab("Number of Hallmark Genes") +
  ylab("Number of Viral Genes") + 
  facet_wrap(~seqtype, scales = "free") +
  coord_flip()


ggplot(viruses_false_positive, aes(x=hallmark, y=checkv_length,
                   fill=checkv_viral_genes,
                   color=checkv_viral_genes,
                   shape=checkv_provirus)) +
  geom_point(alpha=0.3) +
  theme_light() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank(),
    legend.position = "bottom",
    axis.text.y=element_text(size=14),
    axis.text.x=element_text(size=14),
    legend.text=element_text(size=12),
    axis.title=element_text(size=16),
  ) +
  xlab("Number of Hallmark Genes") +
  ylab("Contig Length") + 
  facet_wrap(~seqtype, scales = "free") +
  coord_flip()


ggplot(viruses_false_positive[viruses_false_positive$seqtype=="bacteria"], aes(x=hallmark, y=checkv_length,
                   fill=checkv_viral_genes,
                   color=checkv_viral_genes,
                   shape=checkv_provirus)) +
  geom_point(alpha=0.3) +
  theme_light() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank(),
    legend.position = "bottom",
    axis.text.y=element_text(size=14),
    axis.text.x=element_text(size=14),
    legend.text=element_text(size=12),
    axis.title=element_text(size=16),
  ) +
  xlab("Number of Hallmark Genes") +
  ylab("Contig Length") + 
  facet_wrap(~Kaiju_Viral, scales = "free") +
  coord_flip()


ggplot(viruses_false_positive[viruses_false_positive$seqtype=="fungi"], aes(x=hallmark, y=checkv_length,
                   fill=keep_score_high_precision,
                   color=keep_score_high_precision,
                   shape=checkv_provirus)) +
  geom_point(alpha=0.3) +
  theme_light() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank(),
    legend.position = "bottom",
    axis.text.y=element_text(size=14),
    axis.text.x=element_text(size=14),
    legend.text=element_text(size=12),
    axis.title=element_text(size=16),
  ) +
  xlab("Number of Hallmark Genes") +
  ylab("Contig Length") + 
  facet_wrap(~Kaiju_Viral, scales = "free") +
  coord_flip()


ggplot(viruses_false_positive[viruses_false_positive$seqtype=="protist"], aes(x=hallmark, y=checkv_length,
                   fill=checkv_viral_genes,
                   color=checkv_viral_genes,
                   shape=checkv_provirus)) +
  geom_point(alpha=0.3) +
  theme_light() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank(),
    legend.position = "bottom",
    axis.text.y=element_text(size=14),
    axis.text.x=element_text(size=14),
    legend.text=element_text(size=12),
    axis.title=element_text(size=16),
  ) +
  xlab("Number of Hallmark Genes") +
  ylab("Contig Length") + 
  facet_wrap(~Kaiju_Viral, scales = "free") +
  coord_flip()


ggplot(viruses_false_negative, aes(x=hallmark, y=checkv_length,
                   fill=checkv_viral_genes,
                   color=checkv_viral_genes,
                   shape=checkv_provirus)) +
  geom_point(alpha=0.3) +
  theme_light() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank(),
    legend.position = "bottom",
    axis.text.y=element_text(size=14),
    axis.text.x=element_text(size=14),
    legend.text=element_text(size=12),
    axis.title=element_text(size=16),
  ) +
  xlab("Number of Hallmark Genes") +
  ylab("Contig Length") + 
  facet_wrap(~Kaiju_Viral, scales = "free") +
  coord_flip()


ggplot(viruses_false_negative, aes(x=hallmark, y=checkv_length,
                   fill=keep_score_high_precision,
                   color=keep_score_high_precision,
                   shape=checkv_provirus)) +
  geom_point(alpha=0.3) +
  theme_light() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank(),
    legend.position = "bottom",
    axis.text.y=element_text(size=14),
    axis.text.x=element_text(size=14),
    legend.text=element_text(size=12),
    axis.title=element_text(size=16),
  ) +
  xlab("Number of Hallmark Genes") +
  ylab("Contig Length") + 
  facet_wrap(~Kaiju_Viral, scales = "free") +
  coord_flip()

table(viruses$hallmark[viruses$confusion_matrix_high_precision=="false positive"]>0)

FALSE  TRUE 
  243  1703 
table(viruses$percent_host[viruses$confusion_matrix_high_precision=="false positive"]<50)

FALSE  TRUE 
  855  1091 

high recall example

viruses$keep_score_high_recall <- getting_viral_set_1(viruses, include_deepvirfinder = F,
                                              include_vibrant = T,
                                              include_virsorter2 = F,
                                              include_kaiju = T,
                                              include_tuning = T,
                                              include_virsorter = T)
viruses$confusion_matrix <- "true negative"
viruses$confusion_matrix[viruses$seqtype=="virus" & viruses$keep_score_high_recall<=1] <- "false negative"
viruses$confusion_matrix[viruses$seqtype=="virus" & viruses$keep_score_high_recall>=1] <- "true positive"
viruses$confusion_matrix[viruses$seqtype!="virus" & viruses$keep_score_high_recall>=1] <- "false positive"

visualizing confusion matrix by taxa

confusion_by_taxa <- melt(table(viruses$confusion_matrix, viruses$seqtype, viruses$Index))
Warning in melt(table(viruses$confusion_matrix, viruses$seqtype, viruses$Index)) :
  The melt generic in data.table has been passed a table and will attempt to redirect to the relevant reshape2 method; please note that reshape2 is deprecated, and this redirection is now deprecated as well. To continue using melt methods from reshape2 while both libraries are attached, e.g. melt.list, you can prepend the namespace like reshape2::melt(table(viruses$confusion_matrix, viruses$seqtype, viruses$Index)). In the next version, this warning will become an error.
colnames(confusion_by_taxa) <- c("confusion_matrix", "seqtype","Index", "count")
pal <- ggthemes::tableau_color_pal(palette="Tableau 10", type="regular")
p2 <- ggplot(confusion_by_taxa, aes(x=count, y=as.factor(Index),
                   fill=confusion_matrix,
                   color=confusion_matrix)) +
  geom_bar(stat="identity") +
  theme_light() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank(),
    legend.position = "bottom",
    axis.text.y=element_text(size=14),
    axis.text.x=element_text(size=14),
    legend.text=element_text(size=12),
    axis.title=element_text(size=16),
  ) +
  scale_fill_manual(name="",
                     values = alpha(rev(pal(4)), 0.5),
                    labels=c("false negative", "false positive", 
                             "true negative", "true positive")) +
  scale_color_manual(name="",
                     values = alpha(rev(pal(4)), 1),
                    labels=c("false negative", "false positive", 
                             "true negative", "true positive")) +
  xlab("Number of Sequences") +
  ylab("") + 
  facet_wrap(~seqtype, scales = "free") +
  coord_flip()
p2

Visualizing confusion matrix by number of tools

viruses$keep_score_visualize <- viruses$keep_score
Warning in set(x, j = name, value = value) :
  Column 'keep_score_visualize' does not exist to remove
viruses$keep_score_visualize[viruses$keep_score>1] <- ">1"
viruses$keep_score_visualize <- factor(viruses$keep_score_visualize, 
                                       levels=c("-0.5", "-1", "0", "0.5","1", ">1"))
viruses$keep_score_visualize <- factor(viruses$keep_score_visualize, 
                                       labels=c("≤ 0", "≤ 0", "≤ 0", "0.5","1", "> 1"))
Error in factor(viruses$keep_score_visualize, labels = c("≤ 0", "≤ 0",  : 
  invalid 'labels'; length 6 should be 1 or 0
levels(factor(viruses$keep_score_visualize))
character(0)
pal <- ggthemes::tableau_color_pal(palette="Tableau 20", type="regular")
p1 <- ggplot(viruses, aes(x=as.factor(Index),
                   fill=keep_score_visualize, color=keep_score_visualize)) +
  geom_bar(stat="count", position="stack") +
  theme_light() +
  coord_flip() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank(),
    legend.position = "bottom",
    axis.text.y=element_text(size=14),
    axis.text.x=element_text(size=14),
    legend.text=element_text(size=12),
    axis.title=element_text(size=16)
  ) +
  scale_color_manual(name = 'Viral Score',
                     values = alpha(c(pal(4)), 1)) +
  scale_fill_manual(name = 'Viral Score',
                     values = alpha(c(pal(4)), 0.5)) +
  xlab("Index") +
  ylab("Sequence Count") +
  facet_wrap(~confusion_matrix, scales = "free")
Error in ggplot(viruses, aes(x = as.factor(Index), fill = keep_score_visualize,  : 
  could not find function "ggplot"

ROC

library(pROC)
Type 'citation("pROC")' for a citation.

Attaching package: ‘pROC’

The following objects are masked from ‘package:stats’:

    cov, smooth, var
```{r}
Error: attempt to use zero-length variable name
```{r}
Error: attempt to use zero-length variable name

Sensitivity: The probability that the model predicts a positive outcome for an observation when indeed the outcome is positive. Specificity: The probability that the model predicts a negative outcome for an observation when indeed the outcome is negative.

Pull out Fungi

fungi_1_vb_1_vb_c_fungi <- inner_join(fungi_1,vb_1_vb_c_fungi, on='contig')
Joining, by = c("Index", "seqtype", "contig", "type", "vibrant_quality", "vibrant_prophage")
LS0tCnRpdGxlOiAiVmlyYWwgU2VxdWVuY2UgU29ydGluZyBUb29scyBFdmFsdWF0aW9uIgphdXRob3I6IEJyaWRnZXQgSGVnYXJ0eSwgSmFtZXMgUmlkZGVsbApkYXRlOiAwNy0yMi0yMDIyCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KVGhpcyBSbWFya2Rvd24gZmlsZSBhc3Nlc3NlcyB0aGUgb3V0cHV0IG9mIENoZWNrViwgRGVlcFZpckZpbmRlciwgS2FpanUsClZJQlJBTlQsIFZpclNvcnRlciwgYW5kIFZpclNvcnRlcjIgb24gbXVsdGlwbGUgdHJhaW5pbmcgc2V0cyBvZiBtaWNyb2JpYWwgRE5BLCAKcHJpbWFyaWx5IGZyb20gTkNCSS4gQ3JlYXRlZCBmcm9tIGZ1bmdhbCwgdmlyYWwsIGJhY3RlcmlhbCwgYXJjaGVhZWwsIHByb3Rpc3QsCmFuZCBwbGFzbWlkIEROQSBzZXF1ZW5jZXMKClBsZWFzZSByZWFjaCBvdXQgdG8gSmFtZXMgUmlkZGVsbCAocmlkZGVsbC4yNkBidWNrZXllbWFpbC5vc3UuZWR1KSBvcgpCcmlkZ2V0IEhlZ2FydHkgKGJlaDUzQGNhc2UuZWR1KSByZWdhcmRpbmcgYW55IGlzc3Vlcywgb3Igb3BlbiBhbiBpc3N1ZSBvbiBnaXRodWIuCgpgYGB7ciBzZXR1cC1saWJyYXJ5fQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocGx5cikKbGlicmFyeShyZXNoYXBlMikKbGlicmFyeSh2aXJpZGlzKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGRhdGEudGFibGUpCmxpYnJhcnkocFJPQykKbGlicmFyeShoZXJlKQpgYGAKCiMgSW5wdXRzCjEpIEZvciB0aGlzIHNjcmlwdCdzIGlucHV0cywgdGhlIHVzZXIgbXVzdCBtZXJnZSBlYWNoIHZpcmFsIGlkZW50aWZpY2F0aW9uIAp0b29sIG91dHB1dCBmaWxlIGludG8gb25lIHRhYi1zZXBhcmF0ZWQgZmlsZS4gClJlcGxhY2UgdGhlIGZpbGVuYW1lcyB3aXRoIHRoZWlyIHBhdGhzIGlmIG5lZWRlZCBpbnRvIHRoZSB2YXJpYWJsZXMgaW4gdGhlIAonaW5wdXRzJyBjaHVuay4KCiAgICBHZW5lcmFsIGZpbGVuYW1lcyBmb3IgZWFjaCB0b29sOgogICAgICAgIENoZWNrdjogcXVhbGl0eV9zdW1tYXJ5LnRzdgogICAgICAgIFZJQlJBTlQ6IFZJQlJBTlRfZ2Vub21lX3F1YWxpdHlfJHthc3NlbWJseX0udHN2CiAgICAgICAgVmlyc29ydGVyOiBWSVJTb3J0ZXJfZ2xvYmFsLXBoYWdlLXNpZ25hbC5jc3YKICAgICAgICBWaXJzb3J0ZXIyOiBmaW5hbC12aXJhbC1zY29yZS50c3YKICAgICAgICBEZWVwVmlyRmluZGVyOiAke2Fzc2VtYmx5fS5mYXN0YV9ndDI1MDBicF9kdmZwcmVkLnR4dAogICAgICAgIEthaWp1OiAke2Fzc2VtYmx5fS5rYWlqdS5uYW1lcy5vdXQKCjIpIE1ha2Ugc3VyZSBhbGwgZmFzdGEgaGVhZGVycyAoYXNzZW1ibHksIGNvbnRpZykgYXJlIGNvbnNpc3RlbnQgd2l0aGluIGFuZAphY3Jvc3MgdG9vbHMuIENodW5rcyBmb3IgZWFjaCB0b29sIGRvIGNvbnRhaW4gc29tZSBsaW5lcyBmb3IgY2xlYW5pbmcgdXAgdGhlc2UgCmZlYXR1cmVzLCBidXQgZHVlIHRvIHRoZWlyIHZhcmlhYmlsaXR5IGl0IHdpbGwgYmUgdGhlIHVzZXIncyByZXNwb25zaWJpbGl0eSB0byAKbWFrZSBzdXJlIHRoZXkgbWF0Y2ggYWNyb3NzIHRvb2xzLgoKMykgQ2hlY2sgZWFjaCBjaHVuayBhbmQgZW5zdXJlIGFsbCBjb2x1bW5zIGFyZSBhY2NvdW50ZWQgZm9yLgoKNCkgVGhpcyBzY3JpcHQgaXMgZGVzaWduZWQgZm9yIGNvbnRpZ3MgPiAzMDAwIGJhc2VwYWlycy4gSXQgY2FuIGJlIG1vZGlmaWVkCnRvIGJlIGhpZ2hlciBvciBsb3dlciwgYnV0IGdvaW5nIGxvd2VyIHdpbGwgZ3JlYXRseSBpbmNyZWFzZSB0aGUgc2l6ZSBvZiB0aGUKZGF0YWZyYW1lIGFuZCBtZW1vcnkgdXNhZ2UuCgoKCmBgYHtyIGlucHV0c30KIyBkYXRhc2V0IG5hbWUgZm9yIGZpbGUgb3JnYW5pemF0aW9uIGFuZCBvdXRwdXRzIGZvciBtZXRyaWNzIGZpbGUKZGF0YXNldF9uYW1lIDwtICJ0ZXN0aW5nX3NldCIKIyBjaGVja1YKY2hlY2tWX3BhdGggPC0gIi4uL1Rvb2xPdXRwdXQvdGVzdGluZ19zZXRzX2NoZWNrdl9vdXRwdXQudHN2IgojIFZJQlJBTlQKdmlicmFudF9wYXRoIDwtICIuLi9Ub29sT3V0cHV0L3Rlc3Rpbmdfc2V0c192aWJyYW50X291dHB1dC50c3YiCiMgRGVlcFZpckZpbmRlcgpkdmZfcGF0aCA8LSAiLi4vVG9vbE91dHB1dC90ZXN0aW5nX3NldHNfZGVlcHZpcmZpbmRlcl9vdXRwdXQudHN2IgojIFZpcnNvcnRlcgp2c19wYXRoIDwtICIuLi9Ub29sT3V0cHV0L3Rlc3Rpbmdfc2V0c192aXJzb3J0ZXJfb3V0cHV0LnRzdiIKIyBWaXJzb3J0ZXIyCnZzMl9wYXRoIDwtICIuLi9Ub29sT3V0cHV0L3Rlc3Rpbmdfc2V0c192aXJzb3J0ZXIyX291dHB1dC50c3YiCiMgS2FpanUKa2pfcGF0aCA8LSAiLi4vVG9vbE91dHB1dC9tZXJnZWQubnJldWsua2FpanUubmFtZXMub3V0IgojIEtCIGN1dG9mZgpLQl9DVVRPRkYgPC0gMzAwMApgYGAKCiMgQWxsIFZpcmFsIENvbnRpZ3MKCiMjIGNoZWNrVgpgYGB7cn0KY2hlY2tWIDwtIGZyZWFkKGNoZWNrVl9wYXRoLCAKICAgICAgICAgICAgICAgIHNlcD0iXHQiLAogICAgICAgICAgICAgICAgaGVhZGVyID0gVCwgCiAgICAgICAgICAgICAgICBzZWxlY3QgPSBjKAogICAgICAgICAgICAgICAgICAgICdJbmRleCcsCiAgICAgICAgICAgICAgICAgICAgJ2NvbnRpZ19pZCcsCiAgICAgICAgICAgICAgICAgICAgJ3Byb3ZpcnVzJywKICAgICAgICAgICAgICAgICAgICAnY29tcGxldGVuZXNzJywKICAgICAgICAgICAgICAgICAgICAnY29udGFtaW5hdGlvbicsCiAgICAgICAgICAgICAgICAgICAgJ3ZpcmFsX2dlbmVzJywKICAgICAgICAgICAgICAgICAgICAnaG9zdF9nZW5lcycsCiAgICAgICAgICAgICAgICAgICAgJ2dlbmVfY291bnQnLAogICAgICAgICAgICAgICAgICAgICdjb250aWdfbGVuZ3RoJywKICAgICAgICAgICAgICAgICAgICAnY2hlY2t2X3F1YWxpdHknCiAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgKSAlPiUgCiAgICByZW5hbWUoCiAgICAgICAgY29udGlnID0gY29udGlnX2lkLAogICAgICAgIGNoZWNrdl9wcm92aXJ1cyA9IHByb3ZpcnVzLAogICAgICAgIGNoZWNrdl9jb21wbGV0ZW5lc3MgPSBjb21wbGV0ZW5lc3MsCiAgICAgICAgY2hlY2t2X2NvbnRhbWluYXRpb24gPSBjb250YW1pbmF0aW9uLAogICAgICAgIGNoZWNrdl92aXJhbF9nZW5lcyA9IHZpcmFsX2dlbmVzLAogICAgICAgIGNoZWNrdl9ob3N0X2dlbmVzID0gaG9zdF9nZW5lcywKICAgICAgICBjaGVja3ZfdG90YWxfZ2VuZXMgPSBnZW5lX2NvdW50LAogICAgICAgIGNoZWNrdl9sZW5ndGggPSBjb250aWdfbGVuZ3RoCiAgICAgICAgKQpjaGVja1YkbWV0aG9kID0gJ2NoZWNrdicKY2hlY2tWIDwtIHNlcGFyYXRlKGNoZWNrViwgY29sID0gY29udGlnLCBpbnRvID0gYygic2VxdHlwZSIsICJjb250aWciKSwgc2VwPSItLSIpCmNoZWNrViRjb250aWcgPC0gc3ViKCJcXC4iLCAiXyIsIGNoZWNrViRjb250aWcpCmNoZWNrViRjb250aWcgPC0gc3ViKCJcXHwiLCAiXyIsIGNoZWNrViRjb250aWcpCmNoZWNrViA8LSBjaGVja1ZbIWR1cGxpY2F0ZWQocGFzdGUoY2hlY2tWJGNvbnRpZywgY2hlY2tWJEluZGV4KSksXQpgYGAKCiMjIFZJQlJBTlQKYGBge3J9CnZiX2MgPC0gZnJlYWQodmlicmFudF9wYXRoLAogICAgICAgICAgICAgIGhlYWRlciA9IFQsCiAgICAgICAgICAgICAgc2VwID0gIlx0IiwKICAgICAgICAgICAgICBzZWxlY3QgPSBjKAogICAgICAgICAgICAgICAgICAnSW5kZXgnLAogICAgICAgICAgICAgICAgICAnc2NhZmZvbGQnLAogICAgICAgICAgICAgICAgICAndHlwZScsCiAgICAgICAgICAgICAgICAgICdRdWFsaXR5JwogICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgKSAlPiUKICAgIHJlbmFtZSgKICAgICAgICBjb250aWcgPSBzY2FmZm9sZCwKICAgICAgICB2aWJyYW50X3F1YWxpdHkgPSBRdWFsaXR5CiAgICAgICAgKQp2Yl9jJG1ldGhvZCA8LSAidmlicmFudCIKdmJfYyR2aWJyYW50X3Byb3BoYWdlIDwtICJObyIKdmJfYyR2aWJyYW50X3Byb3BoYWdlW2dyZXAoIl9mcmFnbWVudF8iLCB2Yl9jJGNvbnRpZyldIDwtICJZZXMiCnZiX2MgPC0gc2VwYXJhdGUodmJfYywgY29sID0gY29udGlnLCBpbnRvID0gYygic2VxdHlwZSIsICJjb250aWciKSwgc2VwPSItLSIpCnZiX2MkY29udGlnIDwtIGdzdWIoIl9mcmFnbWVudF8uKiIsICIiLCB2Yl9jJGNvbnRpZykKdmJfYyRjb250aWcgPC0gc3ViKCJcXC4iLCAiXyIsIHZiX2MkY29udGlnKQp2Yl9jIDwtIHNlcGFyYXRlKHZiX2MsIGNvbD1jb250aWcsIGludG89ImNvbnRpZyIsIHJlbW92ZT1ULCBzZXAgPSAiICIpCnZiX2MgPC0gdmJfY1shZHVwbGljYXRlZChwYXN0ZSh2Yl9jJGNvbnRpZywgdmJfYyRJbmRleCkpLF0KYGBgCgojIyBEZWVwVmlyRmluZGVyCmBgYHtyfQpkdmZfYyA8LSBmcmVhZChkdmZfcGF0aCwKICAgICAgICAgICAgICAgaGVhZGVyID0gVCwKICAgICAgICAgICAgICAgc2VwID0gIlx0IiwKICAgICAgICAgICAgICAgc2VsZWN0ID0gYygKICAgICAgICAgICAgICAgICAgICdJbmRleCcsCiAgICAgICAgICAgICAgICAgICAnbmFtZScsCiAgICAgICAgICAgICAgICAgICAnc2NvcmUnLAogICAgICAgICAgICAgICAgICAgJ3B2YWx1ZScKICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgKSAlPiUgCiAgICByZW5hbWUoCiAgICAgICAgY29udGlnID0gbmFtZQogICAgICAgICkKZHZmX2MkY29udGlnIDwtIHN1YigiXFwuIiwgIl8iLCBkdmZfYyRjb250aWcpCmR2Zl9jIDwtIHNlcGFyYXRlKGR2Zl9jLCBjb2wgPSBjb250aWcsIGludG8gPSBjKCJzZXF0eXBlIiwgImNvbnRpZyIpLCBzZXA9Ii0tIikKZHZmX2MkYmhfcHZhbHVlIDwtIHAuYWRqdXN0KGR2Zl9jJHB2YWx1ZSwgbWV0aG9kPSJCSCIpCmR2Zl9jIDwtIGR2Zl9jWyFkdXBsaWNhdGVkKHBhc3RlKGR2Zl9jJGNvbnRpZywgZHZmX2MkSW5kZXgpKSxdCmBgYAoKIyMgVmlyU29ydGVyCmBgYHtyfQp2c19jIDwtIGZyZWFkKHZzX3BhdGgsCiAgICAgICAgICAgICAgc2VsZWN0ID0gYygKICAgICAgICAgICAgICAgICAgJ2luZGV4JywKICAgICAgICAgICAgICAgICAgJ2NvbnRpZycsCiAgICAgICAgICAgICAgICAgICdjYXRlZ29yeScKICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICkgJT4lIAogICAgcmVuYW1lKAogICAgICAgIEluZGV4ID0gaW5kZXgKICAgICAgICApCnZzX2MkY29udGlnIDwtIHN1YigiVklSU29ydGVyXyIsICIiLCB2c19jJGNvbnRpZykKdnNfYyRjb250aWcgPC0gc3ViKCItY2lyY3VsYXIiLCAiIiwgdnNfYyRjb250aWcpCnZzX2MgPC0gc2VwYXJhdGUodnNfYywgY29sID0gYGNvbnRpZ2AsIGludG8gPSBjKCJzZXF0eXBlIiwgImNvbnRpZyIpLCBzZXA9Ii0tIikKdnNfYyRjb250aWcgPC0gc3ViKCJcXC4iLCAiXyIsIHZzX2MkY29udGlnKQp2c19jIDwtIHZzX2MgJT4lIGRyb3BfbmEoY29udGlnKQp2c19jIDwtIHZzX2NbIWR1cGxpY2F0ZWQocGFzdGUodnNfYyRjb250aWcsIHZzX2MkSW5kZXgpKSxdCmBgYAoKCiMjIFZpclNvcnRlcjIgCmBgYHtyfQp2czJfYyA8LSBmcmVhZCh2czJfcGF0aCwKICAgICAgICAgICAgICAgICAgICBoZWFkZXIgPSBULAogICAgICAgICAgICAgICAgICAgIHNlcCA9ICdcdCcsCiAgICAgICAgICAgICAgICAgICAgc2VsZWN0ID0gYygKICAgICAgICAgICAgICAgICAgICAgICAgJ0luZGV4JywKICAgICAgICAgICAgICAgICAgICAgICAgJ3NlcW5hbWUnLAogICAgICAgICAgICAgICAgICAgICAgICAnZHNETkFwaGFnZScsCiAgICAgICAgICAgICAgICAgICAgICAgICdzc0ROQScsCiAgICAgICAgICAgICAgICAgICAgICAgICdtYXhfc2NvcmUnLAogICAgICAgICAgICAgICAgICAgICAgICAnbWF4X3Njb3JlX2dyb3VwJywKICAgICAgICAgICAgICAgICAgICAgICAgJ2hhbGxtYXJrJywKICAgICAgICAgICAgICAgICAgICAgICAgJ3ZpcmFsJywKICAgICAgICAgICAgICAgICAgICAgICAgJ2NlbGx1bGFyJwogICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgKSAlPiUgCiAgICAgICAgICAgICAgc2VwYXJhdGUoCiAgICAgICAgICAgICAgICAgIGNvbCA9IHNlcW5hbWUsCiAgICAgICAgICAgICAgICAgIGludG8gPSBjKCJjb250aWciLCAidnMydHlwZSIpLCAKICAgICAgICAgICAgICAgICAgc2VwID0gIlxcfFxcfCIsCiAgICAgICAgICAgICAgICAgIHJlbW92ZSA9IFQKICAgICAgICAgICAgICAgICAgKQp2czJfYyRjb250aWcgPC0gc3ViKCJcXC4iLCAiXyIsIHZzMl9jJGNvbnRpZykKdnMyX2MgPC0gc2VwYXJhdGUodnMyX2MsIGNvbCA9IGNvbnRpZywgaW50byA9IGMoInNlcXR5cGUiLCAiY29udGlnIiksIHNlcD0iLS0iKQp2czJfYyA8LSB2czJfY1shZHVwbGljYXRlZChwYXN0ZSh2czJfYyRjb250aWcsIHZzMl9jJEluZGV4KSksXQpgYGAKCgojIyBLYWlqdSAKYGBge3J9CmtqX2MgPC0gcmVhZF90c3Yoa2pfcGF0aCwgY29sX25hbWVzID0gVCkKa2pfYyRDb250aWcgPC0gc3ViKCJcXC4iLCAiXyIsIGtqX2MkQ29udGlnKQpral9jIDwtIHNlcGFyYXRlKGtqX2MsIGNvbCA9IENvbnRpZywgaW50byA9IGMoInNlcXR5cGUiLCAiY29udGlnIiksIHNlcD0iLS0iKQpral9jIDwtIHNlcGFyYXRlKGtqX2MsIGNvbCA9IE5hbWUsIGludG8gPSBjKCJLYWlqdV9WaXJhbCIsIktpbmdkb20iKSwgc2VwPSI7IikKa2pfYyRjb250aWcgPC0gc3ViKCJcXC4iLCAiXyIsIGtqX2MkY29udGlnKQpral9jIDwtIGtqX2NbIWR1cGxpY2F0ZWQocGFzdGUoa2pfYyRjb250aWcsIGtqX2MkSW5kZXgpKSxdCmBgYApRdWljayBnbGltcHNlIG9mIGNlbGx1bGFyIHZzIHZpcmFsIHNlcXVlbmNlIGNsYXNzaWZpY2F0aW9uIGJ5IEthaWp1IGJ5IGFzc2VtYmx5CmBgYHtyfQp0YWJsZShral9jJHNlcXR5cGUsIGtqX2MkS2FpanVfVmlyYWwpCmBgYAoKCiMjIE1lcmdpbmcKYGBge3J9CnZpcnVzZXMgPC0gZnVsbF9qb2luKHg9Y2hlY2tWLCB5PWtqX2MsIGJ5ID0gYygiSW5kZXgiLCAiY29udGlnIiwgInNlcXR5cGUiKSkKdmlydXNlcyA8LSBmdWxsX2pvaW4oeD12aXJ1c2VzLCB5PWR2Zl9jLCBieSA9IGMoIkluZGV4IiwgImNvbnRpZyIsICJzZXF0eXBlIikpCnZpcnVzZXMgPC0gZnVsbF9qb2luKHg9dmlydXNlcywgeT12Yl9jLCBieSA9IGMoIkluZGV4IiwgImNvbnRpZyIsICJzZXF0eXBlIikpCnZpcnVzZXMgPC0gZnVsbF9qb2luKHg9dmlydXNlcywgeT12c19jLCBieSA9IGMoIkluZGV4IiwgImNvbnRpZyIsICJzZXF0eXBlIikpCnZpcnVzZXMgPC0gZnVsbF9qb2luKHg9dmlydXNlcywgeT12czJfYywgYnkgPSBjKCJJbmRleCIsICJjb250aWciLCAic2VxdHlwZSIpKQpgYGAKClJlbW92ZSBjb250aWdzIG5vdCBncmVhdGVyIHRoYW4gdGhlIGJhc2VwYWlyIGxlbmd0aCBjdXRvZmYgKDMwMDApCmBgYHtyfQp2aXJ1c2VzIDwtIHZpcnVzZXMgJT4lIGZpbHRlcihjaGVja3ZfbGVuZ3RoID4gS0JfQ1VUT0ZGKQpgYGAKCgpVc2UgdGhlIG5leHQgY29kZSBjaHVuayB0byBjaGVjayBpZiBhbnkgY29udGlncyBhcmUgbWlzc2luZyBmcm9tIGNoZWNrdi4KSWYgeWVzLCB0aGVuIHRoZXJlIGlzIGEgbWl4IHVwIGluIGNvbnRpZyBuYW1lcyBzaW5jZSBjaGVja3Ygc2hvdWxkIGNvbnRhaW4KYWxsIGNvbnRpZyBuYW1lcyBldmVuIGlmIHRoZXkgYXJlIGlkZW50aWZpZWQgYXMgbm9uLXZpcmFsLgpgYGB7cn0Kdl9taXNzaW5nIDwtIHZpcnVzZXNbaXMubmEodmlydXNlcyRjaGVja3ZfdW5pcV9jb250aWcpLF0KYGBgCgpjYWxjdWxhdGUgcGVyY2VudCB2aXJhbC9ob3N0L3Vua25vd24KYGBge3J9CnZpcnVzZXMkcGVyY2VudF9ob3N0IDwtIHZpcnVzZXMkY2hlY2t2X2hvc3RfZ2VuZXMvdmlydXNlcyRjaGVja3ZfdG90YWxfZ2VuZXMqMTAwCnZpcnVzZXMkcGVyY2VudF92aXJhbCA8LSB2aXJ1c2VzJGNoZWNrdl92aXJhbF9nZW5lcy92aXJ1c2VzJGNoZWNrdl90b3RhbF9nZW5lcyoxMDAKdmlydXNlcyRwZXJjZW50X3Vua25vd24gPC0gMTAwLSh2aXJ1c2VzJGNoZWNrdl9ob3N0X2dlbmVzK3ZpcnVzZXMkY2hlY2t2X3ZpcmFsX2dlbmVzKS92aXJ1c2VzJGNoZWNrdl90b3RhbF9nZW5lcyoxMDAKYGBgCgpnZXQgcmlkIG9mIE5BcyBmb3IgZG93bnN0cmVhbSBwcm9jZXNzaW5nCmBgYHtyfQojIGNoZWNrVgp2aXJ1c2VzJHBlcmNlbnRfdmlyYWxbaXMubmEodmlydXNlcyRwZXJjZW50X3ZpcmFsKV0gPC0gMAp2aXJ1c2VzJHBlcmNlbnRfdW5rbm93bltpcy5uYSh2aXJ1c2VzJHBlcmNlbnRfdW5rbm93bildIDwtIDAKIyBWSUJSQU5UCnZpcnVzZXMkdmlicmFudF9xdWFsaXR5W2lzLm5hKHZpcnVzZXMkdmlicmFudF9xdWFsaXR5KV0gPC0gMAojIERlZXBWaXJGaW5kZXIKdmlydXNlcyRzY29yZVtpcy5uYSh2aXJ1c2VzJHNjb3JlKV0gPC0gMAp2aXJ1c2VzJGJoX3B2YWx1ZVtpcy5uYSh2aXJ1c2VzJGJoX3B2YWx1ZSldIDwtIDAKIyBWaXJTb3J0ZXIyCnZpcnVzZXMkdmlyYWxbaXMubmEodmlydXNlcyR2aXJhbCldIDwtIDAKdmlydXNlcyRoYWxsbWFya1tpcy5uYSh2aXJ1c2VzJGhhbGxtYXJrKV0gPC0gMAojVmlyc29ydGVyCnZpcnVzZXMkY2F0ZWdvcnlbaXMubmEodmlydXNlcyRjYXRlZ29yeSldIDwtIDAKIyBLYWlqdQp2aXJ1c2VzJEthaWp1X1ZpcmFsW2lzLm5hKHZpcnVzZXMkS2FpanVfVmlyYWwpXSA8LSAidW5rbm93biIKdmlydXNlcyRLaW5nZG9tW2lzLm5hKHZpcnVzZXMkS2luZ2RvbSldIDwtICJ1bmtub3duIgpgYGAKCgoKVGhpcyBzZWN0aW9uIGRlZmluZXMgYSB2aXJhbG5lc3Mgc2NvcmUgImtlZXBfc2NvcmUiIGJhc2VkIG9uIHRoZSB0b29sIGNsYXNzaWZpY2F0aW9ucy4gCkEgZmluYWwga2VlcF9zY29yZSBhYm92ZSAxIGluZGljYXRlcyB3ZSB3aWxsIGtlZXAgdGhhdCBzZXF1ZW5jZSBhbmQgY2FsbCBpdCB2aXJhbC4KClZJQlJBTlQKICAgIFF1YWxpdHkgPT0gIkhpZ2ggUXVhbGl0eSBEcmFmdCI6ICsxCiAgICBRdWFsaXR5ID09ICJNZWRpdW0gUXVhbGl0eSBEcmFmdCI6ICsxCiAgICBRdWFsaXR5ID09ICJMb3cgUXVhbGl0eSBEcmFmdCIgJiBwcm92aXJ1cyA9PSBUUlVFOiArMC41CgpWaXJzb3J0ZXIyCiAgICBWaXJhbCA+PSA1MDogKzAuNQogICAgVmlyYWwgPj0gMC45NTogKzAuNQoKVmlyc29ydGVyCiAgICBjYXRlZ29yeSA9PSAgMSwyLDQsNTogKzEKICAgIGNhdGVnb3J5ID09IDMsNjogKzAuNQoKRGVlcFZpckZpbmRlcjoKICAgIFNjb3JlID49IDAuNzogKzAuNQogICAgU2NvcmUgPj0gMC45OiArMC41CgpLYWlqdToKICAgIEthaWp1X3ZpcmFsID0gImNlbGx1bGFyIG9yZ2FuaXNtcyI6IC0xCiAgICBLYWlqdV92aXJhbCA9ICJWaXJ1c2VzIjogKzEKCkNoZWNrVgogICAgSWYgJXVua25vd24gPj0gNzU6ICswLjUKICAgIEhhbGxtYXJrID4gMjogKzEKICAgIHZpcmFsX2dlbmVzID09IDAgYW5kIGhvc3RfZ2VuZXMgPj0gMToga2VlcF9zY29yZSA9IDAKICAgIElmIDMqdmlyYWxfZ2VuZXMgPD0gaG9zdF9nZW5lczoga2VlcF9zY29yZSA9IDAKICAgIElmIGxlbmd0aCA+IDUwLDAwMCBhbmQgaGFsbG1hcmsgPT0gMDoga2VlcF9zY29yZSA9IDAKICAgIAoKVGhpcyBzY3JpcHQgcHJvZHVjZXMgdmlzdWFsaXphdGlvbnMgb2YgdGhlc2UgY29tYmluZWQgdmlyYWwgc2NvcmluZ3MgYW5kCmluY2x1ZGVzIGVjb2xvZ2ljYWwgbWV0cmljcyBsaWtlIGFscGhhIGRpdmVyc2l0eS4KCllvdSBjYW4gZGVjaWRlIHdoaWNoIGNvbWJpbmF0aW9uIGlzIGFwcHJvcHJpYXRlIGZvciB0aGVtIGFuZCBvbmx5IG5lZWQgdXNlIHRoZQp0b29scyBhcHByb3ByaWF0ZSBmb3IgeW91ciBkYXRhLgoKYGBge3IgZ2V0dGluZ192aXJhbF9zZXRfMX0KZ2V0dGluZ192aXJhbF9zZXRfMSA8LSBmdW5jdGlvbihpbnB1dF9zZXFzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1ZGVfdmlicmFudD1GQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVkZV92aXJzb3J0ZXIyPUZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1ZGVfZGVlcHZpcmZpbmRlcj1GQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlX3R1bmluZz1GQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlX2thaWp1PUZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1ZGVfdmlyc29ydGVyPUZBTFNFKSB7CiAgCiAga2VlcF9zY29yZSA8LSByZXAoMCwgbnJvdyhpbnB1dF9zZXFzKSkKICAKICBpZiAoaW5jbHVkZV92aWJyYW50KSB7CiAgICBrZWVwX3Njb3JlW2lucHV0X3NlcXMkdmlicmFudF9xdWFsaXR5PT0iaGlnaCBxdWFsaXR5IGRyYWZ0Il0gPC0ga2VlcF9zY29yZVtpbnB1dF9zZXFzJHZpYnJhbnRfcXVhbGl0eT09ImhpZ2ggcXVhbGl0eSBkcmFmdCJdICsgMQogICAga2VlcF9zY29yZVtpbnB1dF9zZXFzJHZpYnJhbnRfcXVhbGl0eT09Im1lZGl1bSBxdWFsaXR5IGRyYWZ0Il0gPC0ga2VlcF9zY29yZVtpbnB1dF9zZXFzJHZpYnJhbnRfcXVhbGl0eT09Im1lZGl1bSBxdWFsaXR5IGRyYWZ0Il0gKyAxCiAgICBrZWVwX3Njb3JlW2lucHV0X3NlcXMkdmlicmFudF9xdWFsaXR5PT0ibG93IHF1YWxpdHkgZHJhZnQiICYgaW5wdXRfc2VxcyRwcm92aXJ1cz09IlllcyJdIDwtIGtlZXBfc2NvcmVbaW5wdXRfc2VxcyR2aWJyYW50X3F1YWxpdHk9PSJsb3cgcXVhbGl0eSBkcmFmdCIgJiBpbnB1dF9zZXFzJHByb3ZpcnVzPT0iWWVzIl0gKyAwLjUKIyAgICBrZWVwX3Njb3JlW2lucHV0X3NlcXMkdmlicmFudF9xdWFsaXR5PT0ibG93IHF1YWxpdHkgZHJhZnQiXSA8LSBrZWVwX3Njb3JlW2lucHV0X3NlcXMkdmlicmFudF9xdWFsaXR5PT0ibG93IHF1YWxpdHkgZHJhZnQiXSArIDAuNQogIH0KICAKICBpZiAoaW5jbHVkZV92aXJzb3J0ZXIyKSB7CiAgICBrZWVwX3Njb3JlW2lucHV0X3NlcXMkdmlyYWw+PTUwXSA8LSBrZWVwX3Njb3JlW2lucHV0X3NlcXMkdmlyYWw+PTUwXSArIDAuNQogICAga2VlcF9zY29yZVtpbnB1dF9zZXFzJHZpcmFsPj05NV0gPC0ga2VlcF9zY29yZVtpbnB1dF9zZXFzJHZpcmFsPj05NV0gKyAwLjUKICB9CiAgCiAgaWYgKGluY2x1ZGVfdmlyc29ydGVyKSB7CiAgICBrZWVwX3Njb3JlW2lucHV0X3NlcXMkY2F0ZWdvcnk9PTFdIDwtIGtlZXBfc2NvcmVbaW5wdXRfc2VxcyRjYXRlZ29yeT09MV0gKyAxCiAgICBrZWVwX3Njb3JlW2lucHV0X3NlcXMkY2F0ZWdvcnk9PTJdIDwtIGtlZXBfc2NvcmVbaW5wdXRfc2VxcyRjYXRlZ29yeT09Ml0gKyAxCiAgICBrZWVwX3Njb3JlW2lucHV0X3NlcXMkY2F0ZWdvcnk9PTNdIDwtIGtlZXBfc2NvcmVbaW5wdXRfc2VxcyRjYXRlZ29yeT09M10gKyAwLjUKICAgIGtlZXBfc2NvcmVbaW5wdXRfc2VxcyRjYXRlZ29yeT09NF0gPC0ga2VlcF9zY29yZVtpbnB1dF9zZXFzJGNhdGVnb3J5PT00XSArIDEKICAgIGtlZXBfc2NvcmVbaW5wdXRfc2VxcyRjYXRlZ29yeT09NV0gPC0ga2VlcF9zY29yZVtpbnB1dF9zZXFzJGNhdGVnb3J5PT01XSArIDEKICAgIGtlZXBfc2NvcmVbaW5wdXRfc2VxcyRjYXRlZ29yeT09Nl0gPC0ga2VlcF9zY29yZVtpbnB1dF9zZXFzJGNhdGVnb3J5PT02XSArIDAuNQogIH0KICAKICBpZiAoaW5jbHVkZV9kZWVwdmlyZmluZGVyKSB7CiAgICBrZWVwX3Njb3JlW2lucHV0X3NlcXMkc2NvcmU+PTAuNyAmIGlucHV0X3NlcXMkY29udGlnX2xlbmd0aDwyMDAwMF0gPC0ga2VlcF9zY29yZVtpbnB1dF9zZXFzJHNjb3JlPj0wLjcgJiBpbnB1dF9zZXFzJGNvbnRpZ19sZW5ndGg8MjAwMDBdICsgMC41CiAgIGtlZXBfc2NvcmVbaW5wdXRfc2VxcyRzY29yZT49MC45ICYgaW5wdXRfc2VxcyRjb250aWdfbGVuZ3RoPDIwMDAwXSA8LSBrZWVwX3Njb3JlW2lucHV0X3NlcXMkc2NvcmU+PTAuOSAmIGlucHV0X3NlcXMkY29udGlnX2xlbmd0aDwyMDAwMF0gKyAwLjUKICB9CiAgCiAgaWYgKGluY2x1ZGVfa2FpanUpIHsKICAgIGtlZXBfc2NvcmVbaW5wdXRfc2VxcyRLYWlqdV9WaXJhbD09ImNlbGx1bGFyIG9yZ2FuaXNtcyJdIDwtIGtlZXBfc2NvcmVbaW5wdXRfc2VxcyRLYWlqdV9WaXJhbD09ImNlbGx1bGFyIG9yZ2FuaXNtcyJdIC0gMQogICAga2VlcF9zY29yZVtpbnB1dF9zZXFzJEthaWp1X1ZpcmFsPT0iVmlydXNlcyJdIDwtIGtlZXBfc2NvcmVbaW5wdXRfc2VxcyRLYWlqdV9WaXJhbD09IlZpcnVzZXMiXSArIDEKICB9CiAgCiAgaWYgKGluY2x1ZGVfdHVuaW5nKSB7CiAgICBrZWVwX3Njb3JlW2lucHV0X3NlcXMkaGFsbG1hcms+Ml0gPC0ga2VlcF9zY29yZVtpbnB1dF9zZXFzJGhhbGxtYXJrPjJdICsgMQogICAga2VlcF9zY29yZVtpbnB1dF9zZXFzJHBlcmNlbnRfdW5rbm93bj49NzVdIDwtIGtlZXBfc2NvcmVbaW5wdXRfc2VxcyRwZXJjZW50X3Vua25vd24+PTc1XSArIDAuNQogICAga2VlcF9zY29yZVtpbnB1dF9zZXFzJHBlcmNlbnRfdmlyYWw+PTUwXSA8LSBrZWVwX3Njb3JlW2lucHV0X3NlcXMkcGVyY2VudF92aXJhbD49NTBdICsgMC41CiAgICAja2VlcF9zY29yZVtpbnB1dF9zZXFzJGhhbGxtYXJrPj0oaW5wdXRfc2VxcyRjaGVja3ZfdmlyYWxfZ2VuZXMvNSldIDwtIGtlZXBfc2NvcmVbaW5wdXRfc2VxcyRoYWxsbWFyaz49KGlucHV0X3NlcXMkY2hlY2t2X3ZpcmFsX2dlbmVzLzUpXSArIDEgI2FkZCBzb21lIHJhdGlvCiAgICBrZWVwX3Njb3JlW2lucHV0X3NlcXMkdmlyYWxfZ2VuZXM9PTAgJiBpbnB1dF9zZXFzJGhvc3RfZ2VuZXM+PTFdIDwtIDAKICAgIGtlZXBfc2NvcmVbKChpbnB1dF9zZXFzJHZpcmFsX2dlbmVzKjMpIDw9IGlucHV0X3NlcXMkaG9zdF9nZW5lcykgJiBpbnB1dF9zZXFzJGNoZWNrdl9wcm92aXJ1cz09Ik5vIl0gPC0gMCAjIGNvbnNpZGVyIGFjY291bnRpbmcgZm9yIHByb3ZpcnVzIGRlc2lnbmF0aW9uCiMgICAga2VlcF9zY29yZVsoaW5wdXRfc2VxcyR2aXJhbF9nZW5lcyozKSA8PSBpbnB1dF9zZXFzJGhvc3RfZ2VuZXNdIDwtIDAgIyBjb25zaWRlciBhY2NvdW50aW5nIGZvciBwcm92aXJ1cyBkZXNpZ25hdGlvbgogICAga2VlcF9zY29yZVtpbnB1dF9zZXFzJGNvbnRpZ19sZW5ndGg+NTAwMDAgJiBpbnB1dF9zZXFzJGhhbGxtYXJrPT0wXSA8LSAwCiAgfQogIAogIHJldHVybihrZWVwX3Njb3JlKQogIAp9CmBgYAoKIyBBc3Nlc3NpbmcgcGVyZm9ybWFuY2UgYWdhaW5zdCB0aGUgInRydXRoIgpub3RlIHRoYXQgdGhpcyBpcyBvbmx5IGFzIGFjY3VyYXRlIGFzIHRoZSBhbm5vdGF0aW9ucyBvZiB0aGUgaW5wdXQgc2VxdWVuY2VzCgp0aGlzIGZ1bmN0aW9uIGNhbGN1bGF0ZXMgdGhlIHByZWNpc2lvbiwgcmVjYWxsLCBhbmQgRjEgc2NvcmUgZm9yIGVhY2ggcGlwZWxpbmUKYGBge3J9CmFzc2Vzc19wZXJmb3JtYW5jZSA8LSBmdW5jdGlvbihzZXF0eXBlLCBrZWVwX3Njb3JlKSB7CiAgCiAgdHJ1ZXBvc2l0aXZlIDwtIHJlcCgibm90IHZpcmFsIiwgbGVuZ3RoKHNlcXR5cGUpKQogIHRydWVwb3NpdGl2ZVtzZXF0eXBlPT0idmlydXMiXSA8LSAidmlyYWwiCiAgCiAgI21ha2UgY29uZnVzaW9uIG1hdHJpeAogIGNvbmZ1c2lvbl9tYXRyaXggPC0gcmVwKCJ0cnVlIG5lZ2F0aXZlIiwgbGVuZ3RoKGtlZXBfc2NvcmUpKQogIGNvbmZ1c2lvbl9tYXRyaXhbdHJ1ZXBvc2l0aXZlPT0idmlyYWwiICYga2VlcF9zY29yZTw9MV0gPC0gImZhbHNlIG5lZ2F0aXZlIgogIGNvbmZ1c2lvbl9tYXRyaXhbdHJ1ZXBvc2l0aXZlPT0idmlyYWwiICYga2VlcF9zY29yZT49MV0gPC0gInRydWUgcG9zaXRpdmUiCiAgY29uZnVzaW9uX21hdHJpeFt0cnVlcG9zaXRpdmU9PSJub3QgdmlyYWwiICYga2VlcF9zY29yZT49MV0gPC0gImZhbHNlIHBvc2l0aXZlIgogIAogIFRQIDwtIHRhYmxlKGNvbmZ1c2lvbl9tYXRyaXgpWzRdCiAgRlAgPC0gdGFibGUoY29uZnVzaW9uX21hdHJpeClbMl0KICBUTiA8LSB0YWJsZShjb25mdXNpb25fbWF0cml4KVszXQogIEZOIDwtIHRhYmxlKGNvbmZ1c2lvbl9tYXRyaXgpWzFdCiAgCiAgcHJlY2lzaW9uIDwtIFRQLyhUUCtGUCkKICByZWNhbGwgPC0gVFAvKFRQK0ZOKQogIEYxIDwtIDIqcHJlY2lzaW9uKnJlY2FsbC8ocHJlY2lzaW9uK3JlY2FsbCkKICAKICBNQ0MgPC0gKFRQKlROLUZQKkZOKS9zcXJ0KGFzLm51bWVyaWMoVFArRlApKmFzLm51bWVyaWMoVFArRk4pKmFzLm51bWVyaWMoVE4rRlApKmFzLm51bWVyaWMoVE4rRk4pKQogIAogIEFVQyA8LSByb3VuZChhdWModHJ1ZXBvc2l0aXZlLCBrZWVwX3Njb3JlKSw0KQogIAogICNieSB0eXBlIG1ldHJpY3MKICBmdW5nYWxfRlAgPC0gdGFibGUoY29uZnVzaW9uX21hdHJpeFtzZXF0eXBlPT0iZnVuZ2kiXSlbMl0KICBiYWN0ZXJpYWxfRlAgPC0gdGFibGUoY29uZnVzaW9uX21hdHJpeFtzZXF0eXBlPT0iYmFjdGVyaWEiXSlbMl0KICB2aXJhbF9GTiA8LSB0YWJsZShjb25mdXNpb25fbWF0cml4W3NlcXR5cGU9PSJ2aXJ1cyJdKVsxXQogIAogIHBlcmZvcm1hbmNlIDwtIGMocHJlY2lzaW9uLCByZWNhbGwsIEYxLCBNQ0MsIEFVQywgZnVuZ2FsX0ZQLCBiYWN0ZXJpYWxfRlAsIHZpcmFsX0ZOKQogIG5hbWVzKHBlcmZvcm1hbmNlKSA8LSBjKCJwcmVjaXNpb24iLCAicmVjYWxsIiwgIkYxIiwgIk1DQyIsICJBVUMiLCAiZnVuZ2FsX0ZQIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAiYmFjdGVyaWFsX0ZQIiwgInZpcmFsX0ZOIikKICAKICByZXR1cm4ocGVyZm9ybWFuY2UpCn0KYGBgCgpjb21iaW5hdGlvbiBvZiB0b29scyBsaXN0CmBgYHtyfQpjb21ib3NfbGlzdCA8LSByZWFkX2NzdigiY29tYmluYXRpb25zX2xpc3QuY3N2IiwgY29sX25hbWVzID0gVCkKYGBgCgp0aGlzIGZ1bmN0aW9uIGJ1aWxkcyBhIGxpc3Qgb2YgYWxsIG9mIHRoZSBjb21iaW5hdGlvbnMgdGhhdCB0aGUgdXNlciB3YW50cyB0byAKdGVzdC4gCkluIHRoaXMgY2FzZSwgd2UncmUgY29tcGFyaW5nIHRoZSBwZXJmb3JtYW5jZSBvZiBhbGwgdW5pcXVlIGNvbWJpbmF0aW9ucyBvZiB0aGUgCnNpeCB0b29scy4KYGBge3J9CmJ1aWxkX3Njb3JlX2xpc3QgPC0gZnVuY3Rpb24oaW5wdXRfc2VxcywgY29tYm9zKSB7CiAgb3V0cHV0IDwtIGRhdGEuZnJhbWUocHJlY2lzaW9uPXJlcCgwLCBucm93KGNvbWJvcykpLAogICAgICAgICAgICAgICAgICAgICAgIHJlY2FsbD1yZXAoMCwgbnJvdyhjb21ib3MpKSwKICAgICAgICAgICAgICAgICAgICAgICBGMT1yZXAoMCwgbnJvdyhjb21ib3MpKSwKICAgICAgICAgICAgICAgICAgICAgICBNQ0M9cmVwKDAsIG5yb3coY29tYm9zKSksCiAgICAgICAgICAgICAgICAgICAgICAgQVVDPXJlcCgwLCBucm93KGNvbWJvcykpLAogICAgICAgICAgICAgICAgICAgICAgIGZ1bmdhbF9GUD1yZXAoMCwgbnJvdyhjb21ib3MpKSwKICAgICAgICAgICAgICAgICAgICAgICBiYWN0ZXJpYWxfRlA9cmVwKDAsIG5yb3coY29tYm9zKSksCiAgICAgICAgICAgICAgICAgICAgICAgdmlyYWxfRk49cmVwKDAsIG5yb3coY29tYm9zKSkpCiAgZm9yIChpIGluIDE6bnJvdyhjb21ib3MpKSB7CiAgICBrZWVwX3Njb3JlIDwtIGdldHRpbmdfdmlyYWxfc2V0XzEoaW5wdXRfc2VxcywgaW5jbHVkZV92aWJyYW50ID0gY29tYm9zJFZJQlJBTlRbaV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVkZV92aXJzb3J0ZXIgPSBjb21ib3MkVlNbaV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVkZV92aXJzb3J0ZXIyID0gY29tYm9zJFZTMltpXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlX3R1bmluZyA9IGNvbWJvcyRDaGVja1ZbaV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVkZV9rYWlqdSA9IGNvbWJvcyRLYWlqdVtpXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlX2RlZXB2aXJmaW5kZXIgPSBjb21ib3MkRFZGW2ldKQogIAogICAgb3V0cHV0W2ksMTo4XSA8LSBhc3Nlc3NfcGVyZm9ybWFuY2UoaW5wdXRfc2VxcyRzZXF0eXBlLCBrZWVwX3Njb3JlKQogICAgCiAgICBvdXRwdXQkdG9vbGNvbWJvW2ldIDwtIHBhc3RlKGNvbWJvcyRDaGVja1ZbaV0sY29tYm9zJERWRltpXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tYm9zJEthaWp1W2ldLCBjb21ib3MkVklCUkFOVFtpXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tYm9zJFZTW2ldLCBjb21ib3MkVlMyW2ldKQogIH0KICAKICBvdXRwdXRbaXMubmEob3V0cHV0KV0gPC0gMAogIAogICNyZXR1cm4oa2VlcF9zY29yZSkKICByZXR1cm4gKG91dHB1dCkKfQpgYGAKCiMjIENhbGN1bGF0ZSB0aGUgcGVyZm9ybWFuY2Ugb2YgZWFjaCBwaXBlbGluZQpgYGB7cn0KYWNjdXJhY3lfc2NvcmVzIDwtIGJ1aWxkX3Njb3JlX2xpc3QodmlydXNlc1t2aXJ1c2VzJEluZGV4PT0xXSwgY29tYm9zX2xpc3QpCmFjY3VyYWN5X3Njb3JlcyA8LSBkYXRhLmZyYW1lKHRlc3Rpbmdfc2V0X2luZGV4PXJlcCgwLCBucm93KGNvbWJvc19saXN0KSoxMCksCiAgICAgICAgICAgICAgICAgICAgICBwcmVjaXNpb249cmVwKDAsIG5yb3coY29tYm9zX2xpc3QpKjEwKSwKICAgICAgICAgICAgICAgICAgICAgICByZWNhbGw9cmVwKDAsIG5yb3coY29tYm9zX2xpc3QpKjEwKSwKICAgICAgICAgICAgICAgICAgICAgICBGMT1yZXAoMCwgbnJvdyhjb21ib3NfbGlzdCkqMTApLAogICAgICAgICAgICAgICAgICAgICAgIE1DQz1yZXAoMCwgbnJvdyhjb21ib3NfbGlzdCkqMTApLCAKICAgICAgICAgICAgICAgICAgICAgIEFVQz1yZXAoMCwgbnJvdyhjb21ib3NfbGlzdCkqMTApLAogICAgICAgICAgICAgICAgICAgICAgZnVuZ2FsX0ZQPXJlcCgwLCBucm93KGNvbWJvc19saXN0KSoxMCksCiAgICAgICAgICAgICAgICAgICAgICBiYWN0ZXJpYWxfRlA9cmVwKDAsIG5yb3coY29tYm9zX2xpc3QpKjEwKSwKICAgICAgICAgICAgICAgICAgICAgIHZpcmFsX0ZOPXJlcCgwLCBucm93KGNvbWJvc19saXN0KSoxMCkpCmFjY3VyYWN5X3Njb3JlcyA8LSBjYmluZCh0ZXN0aW5nX3NldF9pbmRleD1yZXAoMSwgbnJvdyhjb21ib3NfbGlzdCkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidWlsZF9zY29yZV9saXN0KHZpcnVzZXNbdmlydXNlcyRJbmRleD09MV0sIGNvbWJvc19saXN0KSkKZm9yIChpIGluIDI6MTApIHsKICBhY2N1cmFjeV9zY29yZXMgPC0gcmJpbmQoYWNjdXJhY3lfc2NvcmVzLAogICAgICAgICAgICAgICAgICAgICAgICAgICBjYmluZCh0ZXN0aW5nX3NldF9pbmRleD1yZXAoaSwgbnJvdyhjb21ib3NfbGlzdCkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidWlsZF9zY29yZV9saXN0KHZpcnVzZXNbdmlydXNlcyRJbmRleD09aV0sIGNvbWJvc19saXN0KSkpCn0KYGBgCgpgYGB7cn0KbGlicmFyeSgic3RyaW5nciIpCmBgYAoKYGBge3J9CmFjY3VyYWN5X3Njb3JlcyRudW10b29scyA8LSBzdHJfY291bnQoYWNjdXJhY3lfc2NvcmVzJHRvb2xjb21ibywgIjEiKQojYWNjdXJhY3lfc2NvcmVzIDwtIGFjY3VyYWN5X3Njb3Jlc1tvcmRlcihhY2N1cmFjeV9zY29yZXMkbnVtdG9vbHMsIGRlY3JlYXNpbmc9RiksXQphY2N1cmFjeV9zY29yZXMgPC0gYWNjdXJhY3lfc2NvcmVzW29yZGVyKGFjY3VyYWN5X3Njb3JlcyRNQ0MsIGRlY3JlYXNpbmc9RiksXQphY2N1cmFjeV9zY29yZXMkdG9vbGNvbWJvIDwtIGZhY3RvcihhY2N1cmFjeV9zY29yZXMkdG9vbGNvbWJvLCBsZXZlbHMgPSB1bmlxdWUoYWNjdXJhY3lfc2NvcmVzJHRvb2xjb21ibykpCmFjY3VyYWN5X3Njb3JlcyRudW10b29scyA8LSBhcy5mYWN0b3IoYWNjdXJhY3lfc2NvcmVzJG51bXRvb2xzKQpgYGAKCgojIyBWaXN1YWxpemUgaG93IHRoZSBwcmVjaXNpb24sIHJlY2FsbCwgYW5kIEYxIHNjb3JlcyBjaGFuZ2UgYWNyb3NzIHBpcGVsaW5lcy4KYGBge3J9CnBhbCA8LSBnZ3RoZW1lczo6dGFibGVhdV9jb2xvcl9wYWwocGFsZXR0ZT0iVGFibGVhdSAxMCIsIHR5cGU9InJlZ3VsYXIiKQpwMiA8LSBnZ3Bsb3QoYWNjdXJhY3lfc2NvcmVzLCBhZXMoeD10b29sY29tYm8sIHk9RjEsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3I9bnVtdG9vbHMsIGZpbGw9bnVtdG9vbHMpKSArCiAgZ2VvbV9wb2ludChhbHBoYT0wLjUpICsKICB0aGVtZV9saWdodCgpICsKICB0aGVtZSgKICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KHNpemU9MTQpLAogICAgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KHNpemU9MTQsIGFuZ2xlID0gOTApLAogICAgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTIpLAogICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xNiksCiAgKSArCiAgeGxhYigiVG9vbCBDb21iaW5hdGlvbiAoQ1YsIERWRiwgS0osIFZCLCBWUywgVlMyKSIpICsKICB5bGFiKCJGMSBTY29yZSIpCnAyCmdncGxvdChhY2N1cmFjeV9zY29yZXMsIGFlcyh4PXRvb2xjb21ibywgeT1wcmVjaXNpb24sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3I9bnVtdG9vbHMsIGZpbGw9bnVtdG9vbHMpKSArCiAgZ2VvbV9wb2ludChhbHBoYT0wLjUpICsKICB0aGVtZV9saWdodCgpICsKICB0aGVtZSgKICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KHNpemU9MTQpLAogICAgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KHNpemU9MTQsIGFuZ2xlID0gOTApLAogICAgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTIpLAogICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xNiksCiAgKSArCiAgeGxhYigiVG9vbCBDb21iaW5hdGlvbiAoQ1YsIERWRiwgS0osIFZCLCBWUywgVlMyKSIpICsKICB5bGFiKCJQcmVjaXNpb24iKQpnZ3Bsb3QoYWNjdXJhY3lfc2NvcmVzLCBhZXMoeD10b29sY29tYm8sIHk9cmVjYWxsLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yPW51bXRvb2xzLCBmaWxsPW51bXRvb2xzKSkgKwogIGdlb21fcG9pbnQoYWxwaGE9MC41KSArCiAgdGhlbWVfbGlnaHQoKSArCiAgdGhlbWUoCiAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgIGF4aXMudGV4dC55PWVsZW1lbnRfdGV4dChzaXplPTE0KSwKICAgIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChzaXplPTE0LCBhbmdsZSA9IDkwKSwKICAgIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKSwKICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTYpLAogICkgKwogIHhsYWIoIlRvb2wgQ29tYmluYXRpb24gKENWLCBEVkYsIEtKLCBWQiwgVlMsIFZTMikiKSArCiAgeWxhYigiUmVjYWxsIikKZ2dwbG90KGFjY3VyYWN5X3Njb3JlcywgYWVzKHg9cHJlY2lzaW9uLCB5PXJlY2FsbCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcj1udW10b29scywgZmlsbD1udW10b29scykpICsKICBnZW9tX3BvaW50KGFscGhhPTAuNSkgKwogIHRoZW1lX2xpZ2h0KCkgKwogIHRoZW1lKAogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT0xNCksCiAgICBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT0xNCwgYW5nbGUgPSA5MCksCiAgICBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMiksCiAgICBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTE2KSwKICApICsKICB4bGFiKCJQcmVjaXNpb24iKSArCiAgeWxhYigiUmVjYWxsIikKZ2dwbG90KGFjY3VyYWN5X3Njb3JlcywgYWVzKHg9dG9vbGNvbWJvLCB5PWFicyhwcmVjaXNpb24tcmVjYWxsKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcj1udW10b29scywgZmlsbD1udW10b29scykpICsKICBnZW9tX3BvaW50KGFscGhhPTAuNSkgKwogIHRoZW1lX2xpZ2h0KCkgKwogIHRoZW1lKAogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT0xNCksCiAgICBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT0xNCwgYW5nbGUgPSA5MCksCiAgICBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMiksCiAgICBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTE2KSwKICApICsKICB4bGFiKCJUb29sIENvbWJpbmF0aW9uIChDViwgRFZGLCBLSiwgVkIsIFZTLCBWUzIpIikgKwogIHlsYWIoIlByZWNpc2lvbi1SZWNhbGwiKQpnZ3Bsb3QoYWNjdXJhY3lfc2NvcmVzLCBhZXMoeD10b29sY29tYm8sIHk9TUNDLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yPW51bXRvb2xzLCBmaWxsPW51bXRvb2xzKSkgKwogIGdlb21fcG9pbnQoYWxwaGE9MC41KSArCiAgdGhlbWVfbGlnaHQoKSArCiAgdGhlbWUoCiAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgIGF4aXMudGV4dC55PWVsZW1lbnRfdGV4dChzaXplPTE0KSwKICAgIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChzaXplPTE0LCBhbmdsZSA9IDkwKSwKICAgIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKSwKICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTYpLAogICkgKwogIHhsYWIoIlRvb2wgQ29tYmluYXRpb24gKENWLCBEVkYsIEtKLCBWQiwgVlMsIFZTMikiKSArCiAgeWxhYigiTUNDIikKZ2dwbG90KGFjY3VyYWN5X3Njb3JlcywgYWVzKHg9dG9vbGNvbWJvLCB5PUFVQywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcj1udW10b29scywgZmlsbD1udW10b29scykpICsKICBnZW9tX3BvaW50KGFscGhhPTAuNSkgKwogIHRoZW1lX2xpZ2h0KCkgKwogIHRoZW1lKAogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT0xNCksCiAgICBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT0xNCwgYW5nbGUgPSA5MCksCiAgICBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMiksCiAgICBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTE2KSwKICApICsKICB4bGFiKCJUb29sIENvbWJpbmF0aW9uIChDViwgRFZGLCBLSiwgVkIsIFZTLCBWUzIpIikgKwogIHlsYWIoIkFVQyIpCmdncGxvdChhY2N1cmFjeV9zY29yZXMsIGFlcyh4PXRvb2xjb21ibywgeT1mdW5nYWxfRlAsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3I9bnVtdG9vbHMsIGZpbGw9bnVtdG9vbHMpKSArCiAgZ2VvbV9wb2ludChhbHBoYT0wLjUpICsKICB0aGVtZV9saWdodCgpICsKICB0aGVtZSgKICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KHNpemU9MTQpLAogICAgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KHNpemU9MTQsIGFuZ2xlID0gOTApLAogICAgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTIpLAogICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xNiksCiAgKSArCiAgeGxhYigiVG9vbCBDb21iaW5hdGlvbiAoQ1YsIERWRiwgS0osIFZCLCBWUywgVlMyKSIpICsKICB5bGFiKCJGdW5nYWwgRmFsc2UgUG9zaXRpdmVzIikKZ2dwbG90KGFjY3VyYWN5X3Njb3JlcywgYWVzKHg9dG9vbGNvbWJvLCB5PWJhY3RlcmlhbF9GUCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcj1udW10b29scywgZmlsbD1udW10b29scykpICsKICBnZW9tX3BvaW50KGFscGhhPTAuNSkgKwogIHRoZW1lX2xpZ2h0KCkgKwogIHRoZW1lKAogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT0xNCksCiAgICBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT0xNCwgYW5nbGUgPSA5MCksCiAgICBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMiksCiAgICBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTE2KSwKICApICsKICB4bGFiKCJUb29sIENvbWJpbmF0aW9uIChDViwgRFZGLCBLSiwgVkIsIFZTLCBWUzIpIikgKwogIHlsYWIoIkJhY3RlcmlhbCBGYWxzZSBQb3NpdGl2ZXMiKQpnZ3Bsb3QoYWNjdXJhY3lfc2NvcmVzLCBhZXMoeD10b29sY29tYm8sIHk9dmlyYWxfRk4sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3I9bnVtdG9vbHMsIGZpbGw9bnVtdG9vbHMpKSArCiAgZ2VvbV9wb2ludChhbHBoYT0wLjUpICsKICB0aGVtZV9saWdodCgpICsKICB0aGVtZSgKICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KHNpemU9MTQpLAogICAgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KHNpemU9MTQsIGFuZ2xlID0gOTApLAogICAgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTIpLAogICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xNiksCiAgKSArCiAgeGxhYigiVG9vbCBDb21iaW5hdGlvbiAoQ1YsIERWRiwgS0osIFZCLCBWUywgVlMyKSIpICsKICB5bGFiKCJWaXJhbCBGYWxzZSBOZWdhdGl2ZXMiKQpgYGAKCgoKCgoKIyBFeHBlcmltZW50aW5nCgojIyBoaWdoIHByZWNpc2lvbiBleGFtcGxlCmBgYHtyfQp2aXJ1c2VzJGtlZXBfc2NvcmVfaGlnaF9wcmVjaXNpb24gPC0gZ2V0dGluZ192aXJhbF9zZXRfMSh2aXJ1c2VzLCBpbmNsdWRlX2RlZXB2aXJmaW5kZXIgPSBGLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVkZV92aWJyYW50ID0gVCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1ZGVfdmlyc29ydGVyMiA9IEYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlX2thaWp1ID0gVCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1ZGVfdHVuaW5nID0gVCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1ZGVfdmlyc29ydGVyID0gRikKYGBgCgoKYGBge3J9CnZpcnVzZXMkY29uZnVzaW9uX21hdHJpeF9oaWdoX3ByZWNpc2lvbiA8LSAidHJ1ZSBuZWdhdGl2ZSIKdmlydXNlcyRjb25mdXNpb25fbWF0cml4X2hpZ2hfcHJlY2lzaW9uW3ZpcnVzZXMkc2VxdHlwZT09InZpcnVzIiAmIHZpcnVzZXMka2VlcF9zY29yZV9oaWdoX3ByZWNpc2lvbjw9MV0gPC0gImZhbHNlIG5lZ2F0aXZlIgp2aXJ1c2VzJGNvbmZ1c2lvbl9tYXRyaXhfaGlnaF9wcmVjaXNpb25bdmlydXNlcyRzZXF0eXBlPT0idmlydXMiICYgdmlydXNlcyRrZWVwX3Njb3JlX2hpZ2hfcHJlY2lzaW9uPj0xXSA8LSAidHJ1ZSBwb3NpdGl2ZSIKdmlydXNlcyRjb25mdXNpb25fbWF0cml4X2hpZ2hfcHJlY2lzaW9uW3ZpcnVzZXMkc2VxdHlwZSE9InZpcnVzIiAmIHZpcnVzZXMka2VlcF9zY29yZV9oaWdoX3ByZWNpc2lvbj49MV0gPC0gImZhbHNlIHBvc2l0aXZlIgpgYGAKCnZpc3VhbGl6aW5nIGNvbmZ1c2lvbiBtYXRyaXggYnkgdGF4YQpgYGB7cn0KY29uZnVzaW9uX2J5X3RheGEgPC0gbWVsdCh0YWJsZSh2aXJ1c2VzJGNvbmZ1c2lvbl9tYXRyaXhfaGlnaF9wcmVjaXNpb24sIHZpcnVzZXMkc2VxdHlwZSwgdmlydXNlcyRJbmRleCkpCmNvbG5hbWVzKGNvbmZ1c2lvbl9ieV90YXhhKSA8LSBjKCJjb25mdXNpb25fbWF0cml4IiwgInNlcXR5cGUiLCJJbmRleCIsICJjb3VudCIpCmBgYAoKCgpgYGB7cn0KcGFsIDwtIGdndGhlbWVzOjp0YWJsZWF1X2NvbG9yX3BhbChwYWxldHRlPSJUYWJsZWF1IDEwIiwgdHlwZT0icmVndWxhciIpCmBgYAoKYGBge3J9CmdncGxvdChjb25mdXNpb25fYnlfdGF4YSwgYWVzKHg9Y291bnQsIHk9YXMuZmFjdG9yKEluZGV4KSwKICAgICAgICAgICAgICAgICAgIGZpbGw9Y29uZnVzaW9uX21hdHJpeCwKICAgICAgICAgICAgICAgICAgIGNvbG9yPWNvbmZ1c2lvbl9tYXRyaXgpKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSArCiAgdGhlbWVfbGlnaHQoKSArCiAgdGhlbWUoCiAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgIGF4aXMudGV4dC55PWVsZW1lbnRfdGV4dChzaXplPTE0KSwKICAgIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChzaXplPTE0KSwKICAgIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKSwKICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTYpLAogICkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKG5hbWU9IiIsCiAgICAgICAgICAgICAgICAgICAgIHZhbHVlcyA9IGFscGhhKHJldihwYWwoNCkpLCAwLjUpLAogICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJmYWxzZSBuZWdhdGl2ZSIsICJmYWxzZSBwb3NpdGl2ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ0cnVlIG5lZ2F0aXZlIiwgInRydWUgcG9zaXRpdmUiKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbChuYW1lPSIiLAogICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSBhbHBoYShyZXYocGFsKDQpKSwgMSksCiAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoImZhbHNlIG5lZ2F0aXZlIiwgImZhbHNlIHBvc2l0aXZlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInRydWUgbmVnYXRpdmUiLCAidHJ1ZSBwb3NpdGl2ZSIpKSArCiAgeGxhYigiTnVtYmVyIG9mIFNlcXVlbmNlcyIpICsKICB5bGFiKCIiKSArIAogIGZhY2V0X3dyYXAofnNlcXR5cGUsIHNjYWxlcyA9ICJmcmVlIikgKwogIGNvb3JkX2ZsaXAoKQpgYGAKCmBgYHtyfQogZ2dwbG90KHZpcnVzZXMsIGFlcyh4PWNoZWNrdl92aXJhbF9nZW5lcywgeT1jb25mdXNpb25fbWF0cml4X2hpZ2hfcHJlY2lzaW9uLAogICAgICAgICAgICAgICAgICAgZmlsbD1jb25mdXNpb25fbWF0cml4X2hpZ2hfcHJlY2lzaW9uLAogICAgICAgICAgICAgICAgICAgY29sb3I9Y29uZnVzaW9uX21hdHJpeF9oaWdoX3ByZWNpc2lvbikpICsKICBnZW9tX2JveHBsb3QoYWxwaGE9MC4zKSArCiAgdGhlbWVfbGlnaHQoKSArCiAgdGhlbWUoCiAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgIGF4aXMudGV4dC55PWVsZW1lbnRfdGV4dChzaXplPTE0KSwKICAgIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChzaXplPTE0KSwKICAgIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKSwKICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTYpLAogICkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKG5hbWU9IiIsCiAgICAgICAgICAgICAgICAgICAgIHZhbHVlcyA9IGFscGhhKHJldihwYWwoNCkpLCAwLjUpLAogICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJmYWxzZSBuZWdhdGl2ZSIsICJmYWxzZSBwb3NpdGl2ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ0cnVlIG5lZ2F0aXZlIiwgInRydWUgcG9zaXRpdmUiKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbChuYW1lPSIiLAogICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSBhbHBoYShyZXYocGFsKDQpKSwgMSksCiAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoImZhbHNlIG5lZ2F0aXZlIiwgImZhbHNlIHBvc2l0aXZlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInRydWUgbmVnYXRpdmUiLCAidHJ1ZSBwb3NpdGl2ZSIpKSArCiAgeGxhYigiTnVtYmVyIG9mIFZpcmFsIFNlcXVlbmNlcyIpICsKICB5bGFiKCIiKSArIAogIGZhY2V0X3dyYXAofnNlcXR5cGUsIHNjYWxlcyA9ICJmcmVlIikgKwogIGNvb3JkX2ZsaXAoKQoKIGdncGxvdCh2aXJ1c2VzLCBhZXMoeD1wZXJjZW50X3ZpcmFsLCB5PWNvbmZ1c2lvbl9tYXRyaXhfaGlnaF9wcmVjaXNpb24sCiAgICAgICAgICAgICAgICAgICBmaWxsPWNvbmZ1c2lvbl9tYXRyaXhfaGlnaF9wcmVjaXNpb24sCiAgICAgICAgICAgICAgICAgICBjb2xvcj1jb25mdXNpb25fbWF0cml4X2hpZ2hfcHJlY2lzaW9uKSkgKwogIGdlb21fYm94cGxvdChhbHBoYT0wLjMpICsKICB0aGVtZV9saWdodCgpICsKICB0aGVtZSgKICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KHNpemU9MTQpLAogICAgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KHNpemU9MTQpLAogICAgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTIpLAogICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xNiksCiAgKSArCiAgc2NhbGVfZmlsbF9tYW51YWwobmFtZT0iIiwKICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gYWxwaGEocmV2KHBhbCg0KSksIDAuNSksCiAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoImZhbHNlIG5lZ2F0aXZlIiwgImZhbHNlIHBvc2l0aXZlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInRydWUgbmVnYXRpdmUiLCAidHJ1ZSBwb3NpdGl2ZSIpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKG5hbWU9IiIsCiAgICAgICAgICAgICAgICAgICAgIHZhbHVlcyA9IGFscGhhKHJldihwYWwoNCkpLCAxKSwKICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YygiZmFsc2UgbmVnYXRpdmUiLCAiZmFsc2UgcG9zaXRpdmUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAidHJ1ZSBuZWdhdGl2ZSIsICJ0cnVlIHBvc2l0aXZlIikpICsKICB4bGFiKCJQZXJjZW50IEdlbmVzIFZpcmFsIikgKwogIHlsYWIoIiIpICsgCiAgZmFjZXRfd3JhcCh+c2VxdHlwZSwgc2NhbGVzID0gImZyZWUiKSArCiAgY29vcmRfZmxpcCgpCgogZ2dwbG90KHZpcnVzZXMsIGFlcyh4PWhhbGxtYXJrLCB5PWNvbmZ1c2lvbl9tYXRyaXhfaGlnaF9wcmVjaXNpb24sCiAgICAgICAgICAgICAgICAgICBmaWxsPWNvbmZ1c2lvbl9tYXRyaXhfaGlnaF9wcmVjaXNpb24sCiAgICAgICAgICAgICAgICAgICBjb2xvcj1jb25mdXNpb25fbWF0cml4X2hpZ2hfcHJlY2lzaW9uKSkgKwogIGdlb21fYm94cGxvdChhbHBoYT0wLjMpICsKICB0aGVtZV9saWdodCgpICsKICB0aGVtZSgKICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KHNpemU9MTQpLAogICAgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KHNpemU9MTQpLAogICAgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTIpLAogICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xNiksCiAgKSArCiAgc2NhbGVfZmlsbF9tYW51YWwobmFtZT0iIiwKICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gYWxwaGEocmV2KHBhbCg0KSksIDAuNSksCiAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoImZhbHNlIG5lZ2F0aXZlIiwgImZhbHNlIHBvc2l0aXZlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInRydWUgbmVnYXRpdmUiLCAidHJ1ZSBwb3NpdGl2ZSIpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKG5hbWU9IiIsCiAgICAgICAgICAgICAgICAgICAgIHZhbHVlcyA9IGFscGhhKHJldihwYWwoNCkpLCAxKSwKICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YygiZmFsc2UgbmVnYXRpdmUiLCAiZmFsc2UgcG9zaXRpdmUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAidHJ1ZSBuZWdhdGl2ZSIsICJ0cnVlIHBvc2l0aXZlIikpICsKICB4bGFiKCJOdW1iZXIgb2YgSGFsbG1hcmsgR2VuZXMiKSArCiAgeWxhYigiIikgKyAKICBmYWNldF93cmFwKH5zZXF0eXBlLCBzY2FsZXMgPSAiZnJlZSIpICsKICBjb29yZF9mbGlwKCkKIApnZ3Bsb3QodmlydXNlcywgYWVzKHg9aGFsbG1hcmssIHk9Y2hlY2t2X3ZpcmFsX2dlbmVzLAogICAgICAgICAgICAgICAgICAgZmlsbD1jb25mdXNpb25fbWF0cml4X2hpZ2hfcHJlY2lzaW9uLAogICAgICAgICAgICAgICAgICAgY29sb3I9Y29uZnVzaW9uX21hdHJpeF9oaWdoX3ByZWNpc2lvbikpICsKICBnZW9tX3BvaW50KGFscGhhPTAuMykgKwogIHRoZW1lX2xpZ2h0KCkgKwogIHRoZW1lKAogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT0xNCksCiAgICBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT0xNCksCiAgICBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMiksCiAgICBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTE2KSwKICApICsKICBzY2FsZV9maWxsX21hbnVhbChuYW1lPSIiLAogICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSBhbHBoYShyZXYocGFsKDQpKSwgMC41KSwKICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YygiZmFsc2UgbmVnYXRpdmUiLCAiZmFsc2UgcG9zaXRpdmUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAidHJ1ZSBuZWdhdGl2ZSIsICJ0cnVlIHBvc2l0aXZlIikpICsKICBzY2FsZV9jb2xvcl9tYW51YWwobmFtZT0iIiwKICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gYWxwaGEocmV2KHBhbCg0KSksIDEpLAogICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJmYWxzZSBuZWdhdGl2ZSIsICJmYWxzZSBwb3NpdGl2ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ0cnVlIG5lZ2F0aXZlIiwgInRydWUgcG9zaXRpdmUiKSkgKwogIHhsYWIoIk51bWJlciBvZiBIYWxsbWFyayBHZW5lcyIpICsKICB5bGFiKCJOdW1iZXIgb2YgVmlyYWwgR2VuZXMiKSArIAogIGZhY2V0X3dyYXAofnNlcXR5cGUsIHNjYWxlcyA9ICJmcmVlIikgKwogIGNvb3JkX2ZsaXAoKQpgYGAKCmBgYHtyfQp2aXJ1c2VzX2ZhbHNlX3Bvc2l0aXZlIDwtIHZpcnVzZXNbdmlydXNlcyRjb25mdXNpb25fbWF0cml4X2hpZ2hfcHJlY2lzaW9uPT0iZmFsc2UgcG9zaXRpdmUiLF0KdmlydXNlc19mYWxzZV9uZWdhdGl2ZSA8LSB2aXJ1c2VzW3ZpcnVzZXMkY29uZnVzaW9uX21hdHJpeF9oaWdoX3ByZWNpc2lvbj09ImZhbHNlIG5lZ2F0aXZlIixdCmBgYAoKYGBge3J9CmdncGxvdCh2aXJ1c2VzLCBhZXMoeD1oYWxsbWFyaywgeT1jaGVja3ZfdmlyYWxfZ2VuZXMsCiAgICAgICAgICAgICAgICAgICBmaWxsPWNoZWNrdl9sZW5ndGgsCiAgICAgICAgICAgICAgICAgICBjb2xvcj1jaGVja3ZfbGVuZ3RoLAogICAgICAgICAgICAgICAgICAgc2hhcGU9Y2hlY2t2X3Byb3ZpcnVzKSkgKwogIGdlb21fcG9pbnQoYWxwaGE9MC4zKSArCiAgdGhlbWVfbGlnaHQoKSArCiAgdGhlbWUoCiAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgIGF4aXMudGV4dC55PWVsZW1lbnRfdGV4dChzaXplPTE0KSwKICAgIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChzaXplPTE0KSwKICAgIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKSwKICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTYpLAogICkgKwogIHhsYWIoIk51bWJlciBvZiBIYWxsbWFyayBHZW5lcyIpICsKICB5bGFiKCJOdW1iZXIgb2YgVmlyYWwgR2VuZXMiKSArIAogIGZhY2V0X3dyYXAofnNlcXR5cGUsIHNjYWxlcyA9ICJmcmVlIikgKwogIGNvb3JkX2ZsaXAoKQoKZ2dwbG90KHZpcnVzZXNfZmFsc2VfcG9zaXRpdmUsIGFlcyh4PWhhbGxtYXJrLCB5PWNoZWNrdl9sZW5ndGgsCiAgICAgICAgICAgICAgICAgICBmaWxsPWNoZWNrdl92aXJhbF9nZW5lcywKICAgICAgICAgICAgICAgICAgIGNvbG9yPWNoZWNrdl92aXJhbF9nZW5lcywKICAgICAgICAgICAgICAgICAgIHNoYXBlPWNoZWNrdl9wcm92aXJ1cykpICsKICBnZW9tX3BvaW50KGFscGhhPTAuMykgKwogIHRoZW1lX2xpZ2h0KCkgKwogIHRoZW1lKAogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT0xNCksCiAgICBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT0xNCksCiAgICBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMiksCiAgICBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTE2KSwKICApICsKICB4bGFiKCJOdW1iZXIgb2YgSGFsbG1hcmsgR2VuZXMiKSArCiAgeWxhYigiQ29udGlnIExlbmd0aCIpICsgCiAgZmFjZXRfd3JhcCh+c2VxdHlwZSwgc2NhbGVzID0gImZyZWUiKSArCiAgY29vcmRfZmxpcCgpCgpnZ3Bsb3QodmlydXNlc19mYWxzZV9wb3NpdGl2ZVt2aXJ1c2VzX2ZhbHNlX3Bvc2l0aXZlJHNlcXR5cGU9PSJiYWN0ZXJpYSJdLCBhZXMoeD1oYWxsbWFyaywgeT1jaGVja3ZfbGVuZ3RoLAogICAgICAgICAgICAgICAgICAgZmlsbD1jaGVja3ZfdmlyYWxfZ2VuZXMsCiAgICAgICAgICAgICAgICAgICBjb2xvcj1jaGVja3ZfdmlyYWxfZ2VuZXMsCiAgICAgICAgICAgICAgICAgICBzaGFwZT1jaGVja3ZfcHJvdmlydXMpKSArCiAgZ2VvbV9wb2ludChhbHBoYT0wLjMpICsKICB0aGVtZV9saWdodCgpICsKICB0aGVtZSgKICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KHNpemU9MTQpLAogICAgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KHNpemU9MTQpLAogICAgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTIpLAogICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xNiksCiAgKSArCiAgeGxhYigiTnVtYmVyIG9mIEhhbGxtYXJrIEdlbmVzIikgKwogIHlsYWIoIkNvbnRpZyBMZW5ndGgiKSArIAogIGZhY2V0X3dyYXAofkthaWp1X1ZpcmFsLCBzY2FsZXMgPSAiZnJlZSIpICsKICBjb29yZF9mbGlwKCkKCmdncGxvdCh2aXJ1c2VzX2ZhbHNlX3Bvc2l0aXZlW3ZpcnVzZXNfZmFsc2VfcG9zaXRpdmUkc2VxdHlwZT09ImZ1bmdpIl0sIGFlcyh4PWhhbGxtYXJrLCB5PWNoZWNrdl9sZW5ndGgsCiAgICAgICAgICAgICAgICAgICBmaWxsPWtlZXBfc2NvcmVfaGlnaF9wcmVjaXNpb24sCiAgICAgICAgICAgICAgICAgICBjb2xvcj1rZWVwX3Njb3JlX2hpZ2hfcHJlY2lzaW9uLAogICAgICAgICAgICAgICAgICAgc2hhcGU9Y2hlY2t2X3Byb3ZpcnVzKSkgKwogIGdlb21fcG9pbnQoYWxwaGE9MC4zKSArCiAgdGhlbWVfbGlnaHQoKSArCiAgdGhlbWUoCiAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgIGF4aXMudGV4dC55PWVsZW1lbnRfdGV4dChzaXplPTE0KSwKICAgIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChzaXplPTE0KSwKICAgIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKSwKICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTYpLAogICkgKwogIHhsYWIoIk51bWJlciBvZiBIYWxsbWFyayBHZW5lcyIpICsKICB5bGFiKCJDb250aWcgTGVuZ3RoIikgKyAKICBmYWNldF93cmFwKH5LYWlqdV9WaXJhbCwgc2NhbGVzID0gImZyZWUiKSArCiAgY29vcmRfZmxpcCgpCgpnZ3Bsb3QodmlydXNlc19mYWxzZV9wb3NpdGl2ZVt2aXJ1c2VzX2ZhbHNlX3Bvc2l0aXZlJHNlcXR5cGU9PSJwcm90aXN0Il0sIGFlcyh4PWhhbGxtYXJrLCB5PWNoZWNrdl9sZW5ndGgsCiAgICAgICAgICAgICAgICAgICBmaWxsPWNoZWNrdl92aXJhbF9nZW5lcywKICAgICAgICAgICAgICAgICAgIGNvbG9yPWNoZWNrdl92aXJhbF9nZW5lcywKICAgICAgICAgICAgICAgICAgIHNoYXBlPWNoZWNrdl9wcm92aXJ1cykpICsKICBnZW9tX3BvaW50KGFscGhhPTAuMykgKwogIHRoZW1lX2xpZ2h0KCkgKwogIHRoZW1lKAogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT0xNCksCiAgICBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT0xNCksCiAgICBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMiksCiAgICBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTE2KSwKICApICsKICB4bGFiKCJOdW1iZXIgb2YgSGFsbG1hcmsgR2VuZXMiKSArCiAgeWxhYigiQ29udGlnIExlbmd0aCIpICsgCiAgZmFjZXRfd3JhcCh+S2FpanVfVmlyYWwsIHNjYWxlcyA9ICJmcmVlIikgKwogIGNvb3JkX2ZsaXAoKQoKZ2dwbG90KHZpcnVzZXNfZmFsc2VfbmVnYXRpdmUsIGFlcyh4PWhhbGxtYXJrLCB5PWNoZWNrdl9sZW5ndGgsCiAgICAgICAgICAgICAgICAgICBmaWxsPWNoZWNrdl92aXJhbF9nZW5lcywKICAgICAgICAgICAgICAgICAgIGNvbG9yPWNoZWNrdl92aXJhbF9nZW5lcywKICAgICAgICAgICAgICAgICAgIHNoYXBlPWNoZWNrdl9wcm92aXJ1cykpICsKICBnZW9tX3BvaW50KGFscGhhPTAuMykgKwogIHRoZW1lX2xpZ2h0KCkgKwogIHRoZW1lKAogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT0xNCksCiAgICBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT0xNCksCiAgICBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMiksCiAgICBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTE2KSwKICApICsKICB4bGFiKCJOdW1iZXIgb2YgSGFsbG1hcmsgR2VuZXMiKSArCiAgeWxhYigiQ29udGlnIExlbmd0aCIpICsgCiAgZmFjZXRfd3JhcCh+S2FpanVfVmlyYWwsIHNjYWxlcyA9ICJmcmVlIikgKwogIGNvb3JkX2ZsaXAoKQoKZ2dwbG90KHZpcnVzZXNfZmFsc2VfbmVnYXRpdmUsIGFlcyh4PWhhbGxtYXJrLCB5PWNoZWNrdl9sZW5ndGgsCiAgICAgICAgICAgICAgICAgICBmaWxsPWtlZXBfc2NvcmVfaGlnaF9wcmVjaXNpb24sCiAgICAgICAgICAgICAgICAgICBjb2xvcj1rZWVwX3Njb3JlX2hpZ2hfcHJlY2lzaW9uLAogICAgICAgICAgICAgICAgICAgc2hhcGU9Y2hlY2t2X3Byb3ZpcnVzKSkgKwogIGdlb21fcG9pbnQoYWxwaGE9MC4zKSArCiAgdGhlbWVfbGlnaHQoKSArCiAgdGhlbWUoCiAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgIGF4aXMudGV4dC55PWVsZW1lbnRfdGV4dChzaXplPTE0KSwKICAgIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChzaXplPTE0KSwKICAgIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKSwKICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTYpLAogICkgKwogIHhsYWIoIk51bWJlciBvZiBIYWxsbWFyayBHZW5lcyIpICsKICB5bGFiKCJDb250aWcgTGVuZ3RoIikgKyAKICBmYWNldF93cmFwKH5LYWlqdV9WaXJhbCwgc2NhbGVzID0gImZyZWUiKSArCiAgY29vcmRfZmxpcCgpCmBgYAoKCgoKYGBge3J9CnRhYmxlKHZpcnVzZXMkaGFsbG1hcmtbdmlydXNlcyRjb25mdXNpb25fbWF0cml4X2hpZ2hfcHJlY2lzaW9uPT0iZmFsc2UgcG9zaXRpdmUiXT4wKQoKdGFibGUodmlydXNlcyRwZXJjZW50X2hvc3RbdmlydXNlcyRjb25mdXNpb25fbWF0cml4X2hpZ2hfcHJlY2lzaW9uPT0iZmFsc2UgcG9zaXRpdmUiXTw1MCkKYGBgCgoKCiMjIGhpZ2ggcmVjYWxsIGV4YW1wbGUKYGBge3J9CnZpcnVzZXMka2VlcF9zY29yZV9oaWdoX3JlY2FsbCA8LSBnZXR0aW5nX3ZpcmFsX3NldF8xKHZpcnVzZXMsIGluY2x1ZGVfZGVlcHZpcmZpbmRlciA9IEYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlX3ZpYnJhbnQgPSBULAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVkZV92aXJzb3J0ZXIyID0gRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1ZGVfa2FpanUgPSBULAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVkZV90dW5pbmcgPSBULAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVkZV92aXJzb3J0ZXIgPSBUKQpgYGAKCgpgYGB7cn0KdmlydXNlcyRjb25mdXNpb25fbWF0cml4IDwtICJ0cnVlIG5lZ2F0aXZlIgp2aXJ1c2VzJGNvbmZ1c2lvbl9tYXRyaXhbdmlydXNlcyRzZXF0eXBlPT0idmlydXMiICYgdmlydXNlcyRrZWVwX3Njb3JlX2hpZ2hfcmVjYWxsPD0xXSA8LSAiZmFsc2UgbmVnYXRpdmUiCnZpcnVzZXMkY29uZnVzaW9uX21hdHJpeFt2aXJ1c2VzJHNlcXR5cGU9PSJ2aXJ1cyIgJiB2aXJ1c2VzJGtlZXBfc2NvcmVfaGlnaF9yZWNhbGw+PTFdIDwtICJ0cnVlIHBvc2l0aXZlIgp2aXJ1c2VzJGNvbmZ1c2lvbl9tYXRyaXhbdmlydXNlcyRzZXF0eXBlIT0idmlydXMiICYgdmlydXNlcyRrZWVwX3Njb3JlX2hpZ2hfcmVjYWxsPj0xXSA8LSAiZmFsc2UgcG9zaXRpdmUiCmBgYAoKdmlzdWFsaXppbmcgY29uZnVzaW9uIG1hdHJpeCBieSB0YXhhCmBgYHtyfQpjb25mdXNpb25fYnlfdGF4YSA8LSBtZWx0KHRhYmxlKHZpcnVzZXMkY29uZnVzaW9uX21hdHJpeCwgdmlydXNlcyRzZXF0eXBlLCB2aXJ1c2VzJEluZGV4KSkKY29sbmFtZXMoY29uZnVzaW9uX2J5X3RheGEpIDwtIGMoImNvbmZ1c2lvbl9tYXRyaXgiLCAic2VxdHlwZSIsIkluZGV4IiwgImNvdW50IikKYGBgCgoKCmBgYHtyfQpwYWwgPC0gZ2d0aGVtZXM6OnRhYmxlYXVfY29sb3JfcGFsKHBhbGV0dGU9IlRhYmxlYXUgMTAiLCB0eXBlPSJyZWd1bGFyIikKYGBgCgpgYGB7cn0KcDIgPC0gZ2dwbG90KGNvbmZ1c2lvbl9ieV90YXhhLCBhZXMoeD1jb3VudCwgeT1hcy5mYWN0b3IoSW5kZXgpLAogICAgICAgICAgICAgICAgICAgZmlsbD1jb25mdXNpb25fbWF0cml4LAogICAgICAgICAgICAgICAgICAgY29sb3I9Y29uZnVzaW9uX21hdHJpeCkpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsKICB0aGVtZV9saWdodCgpICsKICB0aGVtZSgKICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KHNpemU9MTQpLAogICAgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KHNpemU9MTQpLAogICAgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTIpLAogICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xNiksCiAgKSArCiAgc2NhbGVfZmlsbF9tYW51YWwobmFtZT0iIiwKICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gYWxwaGEocmV2KHBhbCg0KSksIDAuNSksCiAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoImZhbHNlIG5lZ2F0aXZlIiwgImZhbHNlIHBvc2l0aXZlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInRydWUgbmVnYXRpdmUiLCAidHJ1ZSBwb3NpdGl2ZSIpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKG5hbWU9IiIsCiAgICAgICAgICAgICAgICAgICAgIHZhbHVlcyA9IGFscGhhKHJldihwYWwoNCkpLCAxKSwKICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YygiZmFsc2UgbmVnYXRpdmUiLCAiZmFsc2UgcG9zaXRpdmUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAidHJ1ZSBuZWdhdGl2ZSIsICJ0cnVlIHBvc2l0aXZlIikpICsKICB4bGFiKCJOdW1iZXIgb2YgU2VxdWVuY2VzIikgKwogIHlsYWIoIiIpICsgCiAgZmFjZXRfd3JhcCh+c2VxdHlwZSwgc2NhbGVzID0gImZyZWUiKSArCiAgY29vcmRfZmxpcCgpCnAyCmBgYAoKCiMgVmlzdWFsaXppbmcgY29uZnVzaW9uIG1hdHJpeCBieSBudW1iZXIgb2YgdG9vbHMKCgpgYGB7cn0KdmlydXNlcyRrZWVwX3Njb3JlX3Zpc3VhbGl6ZSA8LSB2aXJ1c2VzJGtlZXBfc2NvcmUKdmlydXNlcyRrZWVwX3Njb3JlX3Zpc3VhbGl6ZVt2aXJ1c2VzJGtlZXBfc2NvcmU+MV0gPC0gIj4xIgp2aXJ1c2VzJGtlZXBfc2NvcmVfdmlzdWFsaXplIDwtIGZhY3Rvcih2aXJ1c2VzJGtlZXBfc2NvcmVfdmlzdWFsaXplLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzPWMoIi0wLjUiLCAiLTEiLCAiMCIsICIwLjUiLCIxIiwgIj4xIikpCnZpcnVzZXMka2VlcF9zY29yZV92aXN1YWxpemUgPC0gZmFjdG9yKHZpcnVzZXMka2VlcF9zY29yZV92aXN1YWxpemUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHM9Yygi4omkIDAiLCAi4omkIDAiLCAi4omkIDAiLCAiMC41IiwiMSIsICI+IDEiKSkKYGBgCgpgYGB7cn0KbGV2ZWxzKGZhY3Rvcih2aXJ1c2VzJGtlZXBfc2NvcmVfdmlzdWFsaXplKSkKYGBgCgoKYGBge3J9CnBhbCA8LSBnZ3RoZW1lczo6dGFibGVhdV9jb2xvcl9wYWwocGFsZXR0ZT0iVGFibGVhdSAyMCIsIHR5cGU9InJlZ3VsYXIiKQpwMSA8LSBnZ3Bsb3QodmlydXNlcywgYWVzKHg9YXMuZmFjdG9yKEluZGV4KSwKICAgICAgICAgICAgICAgICAgIGZpbGw9a2VlcF9zY29yZV92aXN1YWxpemUsIGNvbG9yPWtlZXBfc2NvcmVfdmlzdWFsaXplKSkgKwogIGdlb21fYmFyKHN0YXQ9ImNvdW50IiwgcG9zaXRpb249InN0YWNrIikgKwogIHRoZW1lX2xpZ2h0KCkgKwogIGNvb3JkX2ZsaXAoKSArCiAgdGhlbWUoCiAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgIGF4aXMudGV4dC55PWVsZW1lbnRfdGV4dChzaXplPTE0KSwKICAgIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChzaXplPTE0KSwKICAgIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKSwKICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTYpCiAgKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKG5hbWUgPSAnVmlyYWwgU2NvcmUnLAogICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSBhbHBoYShjKHBhbCg0KSksIDEpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwobmFtZSA9ICdWaXJhbCBTY29yZScsCiAgICAgICAgICAgICAgICAgICAgIHZhbHVlcyA9IGFscGhhKGMocGFsKDQpKSwgMC41KSkgKwogIHhsYWIoIkluZGV4IikgKwogIHlsYWIoIlNlcXVlbmNlIENvdW50IikgKwogIGZhY2V0X3dyYXAofmNvbmZ1c2lvbl9tYXRyaXgsIHNjYWxlcyA9ICJmcmVlIikKcDEKYGBgCgoKIyBST0MgCmBgYHtyfQpsaWJyYXJ5KHBST0MpCmBgYAoKYGBge3J9CnZpcnVzZXMkdHJ1ZXBvc2l0aXZlIDwtIHJlcCgwLCBucm93KHZpcnVzZXMpKQp2aXJ1c2VzJHRydWVwb3NpdGl2ZVt2aXJ1c2VzJHNlcXR5cGU9PSJ2aXJ1cyJdIDwtIDEKYGBgCgoKYGBge3J9CnJvY29iaiA8LSByb2ModmlydXNlcyR0cnVlcG9zaXRpdmUsIHZpcnVzZXMka2VlcF9zY29yZSkKcm9jb2JqX2FsbCA8LSByb2ModmlydXNlcyR0cnVlcG9zaXRpdmUsIHZpcnVzZXMka2VlcF9zY29yZV9hbGwpCkFVQyA8LSByb3VuZChhdWModmlydXNlcyR0cnVlcG9zaXRpdmUsIHZpcnVzZXMka2VlcF9zY29yZSksNCkKYXVjX2FsbCA8LSByb3VuZChhdWModmlydXNlcyR0cnVlcG9zaXRpdmUsIHZpcnVzZXMka2VlcF9zY29yZV9hbGwpLDQpCiNjcmVhdGUgUk9DIHBsb3QKZ2dyb2Mocm9jb2JqLCBjb2xvdXIgPSAnc3RlZWxibHVlJywgc2l6ZSA9IDIpICsKICBnZ3RpdGxlKHBhc3RlMCgnUk9DIEN1cnZlICcsICcoQVVDID0gJywgQVVDLCAnKScpKSArCiAgY29vcmRfZXF1YWwoKQpnZ3JvYyhyb2NvYmpfYWxsLCBjb2xvdXIgPSAnZ3JlZW4nLCBzaXplID0gMikgKwogIGdndGl0bGUocGFzdGUwKCdST0MgQ3VydmUgJywgJyhBVUMgPSAnLCBhdWNfYWxsLCAnKScpKQpgYGAKU2Vuc2l0aXZpdHk6IFRoZSBwcm9iYWJpbGl0eSB0aGF0IHRoZSBtb2RlbCBwcmVkaWN0cyBhIHBvc2l0aXZlIG91dGNvbWUgZm9yIGFuIG9ic2VydmF0aW9uIHdoZW4gaW5kZWVkIHRoZSBvdXRjb21lIGlzIHBvc2l0aXZlLgpTcGVjaWZpY2l0eTogVGhlIHByb2JhYmlsaXR5IHRoYXQgdGhlIG1vZGVsIHByZWRpY3RzIGEgbmVnYXRpdmUgb3V0Y29tZSBmb3IgYW4gb2JzZXJ2YXRpb24gd2hlbiBpbmRlZWQgdGhlIG91dGNvbWUgaXMgbmVnYXRpdmUuCgojIyBQdWxsIG91dCBGdW5naQoKYGBge3J9CmZ1bmdpXzEgPC0gdmlydXNlc1sodmlydXNlcyRzZXF0eXBlID09ICJmdW5naSIpICYgKHZpcnVzZXMkS2FpanVfVmlyYWwgPT0gIlZpcnVzZXMiKV0KdmJfMSA8LSByZWFkX3RzdigiL1VzZXJzL3JpZGRlbGxqL0RvY3VtZW50cy9SZXNlYXJjaC9WU1RFL1Ryb3VibGVzaG9vdF9GdW5naS9WSUJSQU5UX2Fubm90YXRpb25zX21ldGFnZW5vbWljX3Rlc3Rpbmdfc2V0XzEudHN2IikKdmJfMSA8LSBzZXBhcmF0ZSh2Yl8xLCBjb2wgPSAic2NhZmZvbGQiLCBpbnRvID0gYygic2VxdHlwZSIsICJjb250aWciKSwgc2VwPSItLSIpCnZiXzEkY29udGlnIDwtIHN1YigiXFwuIiwgIl8iLCB2Yl8xJGNvbnRpZykKdmJfMV92Yl9jIDwtIGlubmVyX2pvaW4odmJfMSwgdmJfYywgb249J2NvbnRpZycpCnZiXzFfdmJfY19mdW5naSA8LSB2Yl8xX3ZiX2MgJT4lIGZpbHRlcihzZXF0eXBlID09ICJmdW5naSIpCgpmdW5naV8xX3ZiXzFfdmJfY19mdW5naSA8LSBpbm5lcl9qb2luKGZ1bmdpXzEsdmJfMV92Yl9jX2Z1bmdpLCBvbj0nY29udGlnJykKCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiNFeGFtcGxlcyBvZiAiZmFsc2UgcG9zaXRpdmUiIGZ1bmdpCiMgaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9udWNjb3JlLzU5OTEyNDc2NQoKYGBg